xref: /petsc/src/sys/classes/viewer/impls/binary/binv.c (revision af7447c59d97c5895530c1d01fa75b051594da19)
1 
2 #include <petsc/private/viewerimpl.h>    /*I   "petscviewer.h"   I*/
3 #include <fcntl.h>
4 #if defined(PETSC_HAVE_UNISTD_H)
5 #include <unistd.h>
6 #endif
7 #if defined(PETSC_HAVE_IO_H)
8 #include <io.h>
9 #endif
10 
11 typedef struct  {
12   int           fdes;                 /* file descriptor, ignored if using MPI IO */
13 #if defined(PETSC_HAVE_MPIIO)
14   PetscBool     usempiio;
15   MPI_File      mfdes;                /* ignored unless using MPI IO */
16   MPI_Offset    moff;
17 #endif
18   PetscFileMode btype;                /* read or write? */
19   FILE          *fdes_info;           /* optional file containing info on binary file*/
20   PetscBool     storecompressed;      /* gzip the write binary file when closing it*/
21   char          *filename;
22   PetscBool     skipinfo;             /* Don't create info file for writing; don't use for reading */
23   PetscBool     skipoptions;          /* don't use PETSc options database when loading */
24   PetscInt      flowcontrol;          /* allow only <flowcontrol> messages outstanding at a time while doing IO */
25   PetscBool     skipheader;           /* don't write header, only raw data */
26   PetscBool     matlabheaderwritten;  /* if format is PETSC_VIEWER_BINARY_MATLAB has the MATLAB .info header been written yet */
27   PetscBool     setfromoptionscalled;
28 } PetscViewer_Binary;
29 
30 static PetscErrorCode PetscViewerGetSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
31 {
32   int                rank;
33   PetscErrorCode     ierr;
34   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data,*obinary;
35 
36   PetscFunctionBegin;
37   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
38   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
39   if (!rank) {
40     ierr    = PetscViewerCreate(PETSC_COMM_SELF,outviewer);CHKERRQ(ierr);
41     ierr    = PetscViewerSetType(*outviewer,PETSCVIEWERBINARY);CHKERRQ(ierr);
42     obinary = (PetscViewer_Binary*)(*outviewer)->data;
43     ierr    = PetscMemcpy(obinary,vbinary,sizeof(PetscViewer_Binary));CHKERRQ(ierr);
44   } SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Cannot get subcomm viewer for binary files or sockets unless SubViewer contains the rank 0 process");
45   PetscFunctionReturn(0);
46 }
47 
48 static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
49 {
50   PetscErrorCode ierr;
51   PetscErrorCode rank;
52 
53   PetscFunctionBegin;
54   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
55   if (!rank) {
56     ierr = PetscFree((*outviewer)->data);CHKERRQ(ierr);
57     ierr = PetscHeaderDestroy(outviewer);CHKERRQ(ierr);
58   }
59   PetscFunctionReturn(0);
60 }
61 
62 #if defined(PETSC_HAVE_MPIIO)
63 /*@C
64     PetscViewerBinaryGetMPIIOOffset - Gets the current offset that should be passed to MPI_File_set_view()
65 
66     Not Collective
67 
68     Input Parameter:
69 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
70 
71     Output Parameter:
72 .    off - the current offset
73 
74     Level: advanced
75 
76     Fortran Note:
77     This routine is not supported in Fortran.
78 
79     Use PetscViewerBinaryAddMPIIOOffset() to increase this value after you have written a view.
80 
81   Concepts: file descriptor^getting
82   Concepts: PetscViewerBinary^accessing file descriptor
83 
84 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryAddMPIIOOffset()
85 @*/
86 PetscErrorCode PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer,MPI_Offset *off)
87 {
88   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
89 
90   PetscFunctionBegin;
91   *off = vbinary->moff;
92   PetscFunctionReturn(0);
93 }
94 
95 /*@C
96     PetscViewerBinaryAddMPIIOOffset - Adds to the current offset that should be passed to MPI_File_set_view()
97 
98     Not Collective
99 
100     Input Parameters:
101 +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
102 -    off - the addition to the offset
103 
104     Level: advanced
105 
106     Fortran Note:
107     This routine is not supported in Fortran.
108 
109     Use PetscViewerBinaryGetMPIIOOffset() to get the value that you should pass to MPI_File_set_view()
110 
111   Concepts: file descriptor^getting
112   Concepts: PetscViewerBinary^accessing file descriptor
113 
114 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
115 @*/
116 PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer,MPI_Offset off)
117 {
118   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
119 
120   PetscFunctionBegin;
121   vbinary->moff += off;
122   PetscFunctionReturn(0);
123 }
124 
125 /*@C
126     PetscViewerBinaryGetMPIIODescriptor - Extracts the MPI IO file descriptor from a PetscViewer.
127 
128     Not Collective
129 
130     Input Parameter:
131 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
132 
133     Output Parameter:
134 .   fdes - file descriptor
135 
136     Level: advanced
137 
138     Fortran Note:
139     This routine is not supported in Fortran.
140 
141   Concepts: file descriptor^getting
142   Concepts: PetscViewerBinary^accessing file descriptor
143 
144 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
145 @*/
146 PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer,MPI_File *fdes)
147 {
148   PetscErrorCode     ierr;
149   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
150 
151   PetscFunctionBegin;
152   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
153   *fdes = vbinary->mfdes;
154   PetscFunctionReturn(0);
155 }
156 
157 static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer,PetscBool  *flg)
158 {
159   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
160 
161   PetscFunctionBegin;
162   *flg = vbinary->usempiio;
163   PetscFunctionReturn(0);
164 }
165 #endif
166 
167 
168 /*@C
169     PetscViewerBinaryGetUseMPIIO - Returns PETSC_TRUE if the binary viewer uses MPI-IO.
170 
171     Not Collective
172 
173     Input Parameter:
174 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
175 
176     Output Parameter:
177 -   flg - PETSC_TRUE if MPI-IO is being used
178 
179     Options Database:
180     -viewer_binary_mpiio : Flag for using MPI-IO
181 
182     Level: advanced
183 
184     Note:
185     If MPI-IO is not available, this function will always return PETSC_FALSE
186 
187     Fortran Note:
188     This routine is not supported in Fortran.
189 
190   Concepts: file descriptor^getting
191   Concepts: PetscViewerBinary^accessing file descriptor
192 
193 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
194 @*/
195 PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool *flg)
196 {
197   PetscErrorCode ierr;
198 
199   PetscFunctionBegin;
200   *flg = PETSC_FALSE;
201   ierr = PetscTryMethod(viewer,"PetscViewerBinaryGetUseMPIIO_C",(PetscViewer,PetscBool*),(viewer,flg));CHKERRQ(ierr);
202   PetscFunctionReturn(0);
203 }
204 
205 static PetscErrorCode  PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt *fc)
206 {
207   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
208 
209   PetscFunctionBegin;
210   *fc = vbinary->flowcontrol;
211   PetscFunctionReturn(0);
212 }
213 
214 /*@C
215     PetscViewerBinaryGetFlowControl - Returns how many messages are allowed to outstanding at the same time during parallel IO reads/writes
216 
217     Not Collective
218 
219     Input Parameter:
220 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
221 
222     Output Parameter:
223 .   fc - the number of messages
224 
225     Level: advanced
226 
227 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinarySetFlowControl()
228 
229 @*/
230 PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt *fc)
231 {
232   PetscErrorCode ierr;
233 
234   PetscFunctionBegin;
235   ierr = PetscUseMethod(viewer,"PetscViewerBinaryGetFlowControl_C",(PetscViewer,PetscInt*),(viewer,fc));CHKERRQ(ierr);
236   PetscFunctionReturn(0);
237 }
238 
239 static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc)
240 {
241   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
242 
243   PetscFunctionBegin;
244   if (fc <= 1) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_OUTOFRANGE,"Flow control count must be greater than 1, %D was set",fc);
245   vbinary->flowcontrol = fc;
246   PetscFunctionReturn(0);
247 }
248 
249 /*@C
250     PetscViewerBinarySetFlowControl - Sets how many messages are allowed to outstanding at the same time during parallel IO reads/writes
251 
252     Not Collective
253 
254     Input Parameter:
255 +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
256 -   fc - the number of messages, defaults to 256 if this function was not called
257 
258     Level: advanced
259 
260 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetFlowControl()
261 
262 @*/
263 PetscErrorCode  PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc)
264 {
265   PetscErrorCode ierr;
266 
267   PetscFunctionBegin;
268   ierr = PetscUseMethod(viewer,"PetscViewerBinarySetFlowControl_C",(PetscViewer,PetscInt),(viewer,fc));CHKERRQ(ierr);
269   PetscFunctionReturn(0);
270 }
271 
272 /*@C
273     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.
274 
275     Collective On PetscViewer
276 
277     Input Parameter:
278 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
279 
280     Output Parameter:
281 .   fdes - file descriptor
282 
283     Level: advanced
284 
285     Notes:
286       For writable binary PetscViewers, the descriptor will only be valid for the
287     first processor in the communicator that shares the PetscViewer. For readable
288     files it will only be valid on nodes that have the file. If node 0 does not
289     have the file it generates an error even if another node does have the file.
290 
291     Fortran Note:
292     This routine is not supported in Fortran.
293 
294     Developer Notes: This must be called on all processes because Dave May changed
295     the source code that this may be trigger a PetscViewerSetUp() call if it was not previously triggered.
296 
297 
298   Concepts: file descriptor^getting
299   Concepts: PetscViewerBinary^accessing file descriptor
300 
301 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
302 @*/
303 PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
304 {
305   PetscErrorCode     ierr;
306   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
307 
308   PetscFunctionBegin;
309   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
310   *fdes = vbinary->fdes;
311   PetscFunctionReturn(0);
312 }
313 
314 /*@
315     PetscViewerBinarySkipInfo - Binary file will not have .info file created with it
316 
317     Not Collective
318 
319     Input Paramter:
320 .   viewer - PetscViewer context, obtained from PetscViewerCreate()
321 
322     Options Database Key:
323 .   -viewer_binary_skip_info
324 
325     Level: advanced
326 
327     Notes: This must be called after PetscViewerSetType(). If you use PetscViewerBinaryOpen() then
328     you can only skip the info file with the -viewer_binary_skip_info flag. To use the function you must open the
329     viewer with PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinarySkipInfo().
330 
331     The .info contains meta information about the data in the binary file, for example the block size if it was
332     set for a vector or matrix.
333 
334    Concepts: PetscViewerBinary^accessing info file
335 
336 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
337           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
338 @*/
339 PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
340 {
341   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
342 
343   PetscFunctionBegin;
344   vbinary->skipinfo = PETSC_TRUE;
345   PetscFunctionReturn(0);
346 }
347 
348 static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip)
349 {
350   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
351 
352   PetscFunctionBegin;
353   vbinary->skipinfo = skip;
354   PetscFunctionReturn(0);
355 }
356 
357 /*@
358     PetscViewerBinarySetSkipInfo - Binary file will not have .info file created with it
359 
360     Not Collective
361 
362     Input Paramter:
363 .   viewer - PetscViewer context, obtained from PetscViewerCreate()
364 
365     Options Database Key:
366 .   -viewer_binary_skip_info
367 
368     Level: advanced
369 
370     Concepts: PetscViewerBinary^accessing info file
371 
372 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
373           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
374 @*/
375 PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer,PetscBool skip)
376 {
377   PetscErrorCode ierr;
378 
379   PetscFunctionBegin;
380   ierr = PetscUseMethod(viewer,"PetscViewerBinarySetSkipInfo_C",(PetscViewer,PetscBool),(viewer,skip));CHKERRQ(ierr);
381   PetscFunctionReturn(0);
382 }
383 
384 static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool *skip)
385 {
386   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
387 
388   PetscFunctionBegin;
389   *skip  = vbinary->skipinfo;
390   PetscFunctionReturn(0);
391 }
392 
393 /*@
394     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file
395 
396     Not Collective
397 
398     Input Parameter:
399 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
400 
401     Output Parameter:
402 .   skip - PETSC_TRUE implies the .info file was not generated
403 
404     Level: advanced
405 
406     Notes: This must be called after PetscViewerSetType()
407 
408     Concepts: PetscViewerBinary^accessing info file
409 
410 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
411           PetscViewerBinarySetSkipOptions(), PetscViewerBinarySetSkipInfo()
412 @*/
413 PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip)
414 {
415   PetscErrorCode ierr;
416 
417   PetscFunctionBegin;
418   ierr = PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip));CHKERRQ(ierr);
419   PetscFunctionReturn(0);
420 }
421 
422 static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)
423 {
424   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
425 
426   PetscFunctionBegin;
427   vbinary->skipoptions = skip;
428   PetscFunctionReturn(0);
429 }
430 
431 /*@
432     PetscViewerBinarySetSkipOptions - do not use the PETSc options database when loading objects
433 
434     Not Collective
435 
436     Input Parameters:
437 +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
438 -   skip - PETSC_TRUE means do not use
439 
440     Options Database Key:
441 .   -viewer_binary_skip_options
442 
443     Level: advanced
444 
445     Notes: This must be called after PetscViewerSetType()
446 
447    Concepts: PetscViewerBinary^accessing info file
448 
449 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
450           PetscViewerBinaryGetSkipOptions()
451 @*/
452 PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscBool skip)
453 {
454   PetscErrorCode ierr;
455 
456   PetscFunctionBegin;
457   ierr = PetscUseMethod(viewer,"PetscViewerBinarySetSkipOptions_C",(PetscViewer,PetscBool),(viewer,skip));CHKERRQ(ierr);
458   PetscFunctionReturn(0);
459 }
460 
461 static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer,PetscBool *skip)
462 {
463   PetscViewer_Binary *vbinary;
464 
465   PetscFunctionBegin;
466   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
467   vbinary = (PetscViewer_Binary*)viewer->data;
468   *skip   = vbinary->skipoptions;
469   PetscFunctionReturn(0);
470 }
471 
472 /*@
473     PetscViewerBinaryGetSkipOptions - checks if viewer uses the PETSc options database when loading objects
474 
475     Not Collective
476 
477     Input Parameter:
478 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
479 
480     Output Parameter:
481 .   skip - PETSC_TRUE means do not use
482 
483     Level: advanced
484 
485     Notes: This must be called after PetscViewerSetType()
486 
487    Concepts: PetscViewerBinary^accessing info file
488 
489 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
490           PetscViewerBinarySetSkipOptions()
491 @*/
492 PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool *skip)
493 {
494   PetscErrorCode ierr;
495 
496   PetscFunctionBegin;
497   ierr = PetscUseMethod(viewer,"PetscViewerBinaryGetSkipOptions_C",(PetscViewer,PetscBool*),(viewer,skip));CHKERRQ(ierr);
498   PetscFunctionReturn(0);
499 }
500 
501 static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip)
502 {
503   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
504 
505   PetscFunctionBegin;
506   vbinary->skipheader = skip;
507   PetscFunctionReturn(0);
508 }
509 
510 /*@
511     PetscViewerBinarySetSkipHeader - do not write a header with size information on output, just raw data
512 
513     Not Collective
514 
515     Input Parameters:
516 +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
517 -   skip - PETSC_TRUE means do not write header
518 
519     Options Database Key:
520 .   -viewer_binary_skip_header
521 
522     Level: advanced
523 
524     Notes: This must be called after PetscViewerSetType()
525 
526            Can ONLY be called on a binary viewer
527 
528 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
529           PetscViewerBinaryGetSkipHeader()
530 @*/
531 PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)
532 {
533   PetscErrorCode ierr;
534 
535   PetscFunctionBegin;
536   ierr = PetscUseMethod(viewer,"PetscViewerBinarySetSkipHeader_C",(PetscViewer,PetscBool),(viewer,skip));CHKERRQ(ierr);
537   PetscFunctionReturn(0);
538 }
539 
540 static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer,PetscBool  *skip)
541 {
542   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
543 
544   PetscFunctionBegin;
545   *skip = vbinary->skipheader;
546   PetscFunctionReturn(0);
547 }
548 
549 /*@
550     PetscViewerBinaryGetSkipHeader - checks whether to write a header with size information on output, or just raw data
551 
552     Not Collective
553 
554     Input Parameter:
555 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
556 
557     Output Parameter:
558 .   skip - PETSC_TRUE means do not write header
559 
560     Level: advanced
561 
562     Notes: This must be called after PetscViewerSetType()
563 
564             Returns false for PETSCSOCKETVIEWER, you cannot skip the header for it.
565 
566 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
567           PetscViewerBinarySetSkipHeader()
568 @*/
569 PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer,PetscBool  *skip)
570 {
571   PetscErrorCode ierr;
572 
573   PetscFunctionBegin;
574   *skip = PETSC_FALSE;
575   ierr  = PetscUseMethod(viewer,"PetscViewerBinaryGetSkipHeader_C",(PetscViewer,PetscBool*),(viewer,skip));CHKERRQ(ierr);
576   PetscFunctionReturn(0);
577 }
578 
579 static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE **file)
580 {
581   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
582   PetscErrorCode     ierr;
583   MPI_Comm           comm;
584 
585   PetscFunctionBegin;
586   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
587   *file = vbinary->fdes_info;
588   if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
589     vbinary->matlabheaderwritten = PETSC_TRUE;
590     ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
591     ierr = PetscFPrintf(comm,*file,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");CHKERRQ(ierr);
592     ierr = PetscFPrintf(comm,*file,"#$$ Set.filename = '%s';\n",vbinary->filename);CHKERRQ(ierr);
593     ierr = PetscFPrintf(comm,*file,"#$$ fd = PetscOpenFile(Set.filename);\n");CHKERRQ(ierr);
594     ierr = PetscFPrintf(comm,*file,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");CHKERRQ(ierr);
595   }
596   PetscFunctionReturn(0);
597 }
598 
599 /*@C
600     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
601           info file associated with a binary file.
602 
603     Not Collective
604 
605     Input Parameter:
606 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
607 
608     Output Parameter:
609 .   file - file pointer  Always returns NULL if not a binary viewer
610 
611     Level: advanced
612 
613     Notes:
614       For writable binary PetscViewers, the descriptor will only be valid for the
615     first processor in the communicator that shares the PetscViewer.
616 
617     Fortran Note:
618     This routine is not supported in Fortran.
619 
620   Concepts: PetscViewerBinary^accessing info file
621 
622 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
623 @*/
624 PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
625 {
626   PetscErrorCode ierr;
627 
628   PetscFunctionBegin;
629   *file = NULL;
630   ierr  = PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file));CHKERRQ(ierr);
631   PetscFunctionReturn(0);
632 }
633 
634 static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
635 {
636   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
637   PetscErrorCode     ierr;
638   PetscMPIInt        rank;
639   int                err;
640 
641   PetscFunctionBegin;
642   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);CHKERRQ(ierr);
643   if ((!rank || vbinary->btype == FILE_MODE_READ) && vbinary->fdes) {
644     close(vbinary->fdes);
645     if (!rank && vbinary->storecompressed) {
646       char par[PETSC_MAX_PATH_LEN],buf[PETSC_MAX_PATH_LEN];
647       FILE *fp;
648       /* compress the file */
649       ierr = PetscStrcpy(par,"gzip -f ");CHKERRQ(ierr);
650       ierr = PetscStrcat(par,vbinary->filename);CHKERRQ(ierr);
651 #if defined(PETSC_HAVE_POPEN)
652       ierr = PetscPOpen(PETSC_COMM_SELF,NULL,par,"r",&fp);CHKERRQ(ierr);
653       if (fgets(buf,1024,fp)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error from command %s\n%s",par,buf);
654       ierr = PetscPClose(PETSC_COMM_SELF,fp,NULL);CHKERRQ(ierr);
655 #else
656       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
657 #endif
658     }
659   }
660   if (vbinary->fdes_info) {
661     err = fclose(vbinary->fdes_info);
662     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
663   }
664   PetscFunctionReturn(0);
665 }
666 
667 #if defined(PETSC_HAVE_MPIIO)
668 static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
669 {
670   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
671   int                err;
672   PetscErrorCode     ierr;
673 
674   PetscFunctionBegin;
675   if (vbinary->mfdes) {
676     ierr = MPI_File_close(&vbinary->mfdes);CHKERRQ(ierr);
677   }
678   if (vbinary->fdes_info) {
679     err = fclose(vbinary->fdes_info);
680     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
681   }
682   PetscFunctionReturn(0);
683 }
684 #endif
685 
686 static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
687 {
688   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
689   PetscErrorCode     ierr;
690 
691   PetscFunctionBegin;
692   if (v->format == PETSC_VIEWER_BINARY_MATLAB) {
693     MPI_Comm comm;
694     FILE     *info;
695 
696     ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr);
697     ierr = PetscViewerBinaryGetInfoPointer(v,&info);CHKERRQ(ierr);
698     ierr = PetscFPrintf(comm,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");CHKERRQ(ierr);
699     ierr = PetscFPrintf(comm,info,"#$$ close(fd);\n");CHKERRQ(ierr);
700     ierr = PetscFPrintf(comm,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");CHKERRQ(ierr);
701   }
702 #if defined(PETSC_HAVE_MPIIO)
703   if (vbinary->usempiio) {
704     ierr = PetscViewerFileClose_BinaryMPIIO(v);CHKERRQ(ierr);
705   } else {
706 #endif
707     ierr = PetscViewerFileClose_Binary(v);CHKERRQ(ierr);
708 #if defined(PETSC_HAVE_MPIIO)
709   }
710 #endif
711   if (vbinary->filename) { ierr = PetscFree(vbinary->filename);CHKERRQ(ierr); }
712   ierr = PetscFree(vbinary);CHKERRQ(ierr);
713   PetscFunctionReturn(0);
714 }
715 
716 /*@C
717    PetscViewerBinaryOpen - Opens a file for binary input/output.
718 
719    Collective on MPI_Comm
720 
721    Input Parameters:
722 +  comm - MPI communicator
723 .  name - name of file
724 -  type - type of file
725 $    FILE_MODE_WRITE - create new file for binary output
726 $    FILE_MODE_READ - open existing file for binary input
727 $    FILE_MODE_APPEND - open existing file for binary output
728 
729    Output Parameter:
730 .  binv - PetscViewer for binary input/output to use with the specified file
731 
732     Options Database Keys:
733 +    -viewer_binary_filename <name>
734 .    -viewer_binary_skip_info
735 .    -viewer_binary_skip_options
736 .    -viewer_binary_skip_header
737 -    -viewer_binary_mpiio
738 
739    Level: beginner
740 
741    Note:
742    This PetscViewer should be destroyed with PetscViewerDestroy().
743 
744     For reading files, the filename may begin with ftp:// or http:// and/or
745     end with .gz; in this case file is brought over and uncompressed.
746 
747     For creating files, if the file name ends with .gz it is automatically
748     compressed when closed.
749 
750     For writing files it only opens the file on processor 0 in the communicator.
751     For readable files it opens the file on all nodes that have the file. If
752     node 0 does not have the file it generates an error even if other nodes
753     do have the file.
754 
755    Concepts: binary files
756    Concepts: PetscViewerBinary^creating
757    Concepts: gzip
758    Concepts: accessing remote file
759    Concepts: remote file
760 
761 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
762           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
763           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead(), PetscViewerBinarySetUseMPIIO(),
764           PetscViewerBinaryGetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
765 @*/
766 PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
767 {
768   PetscErrorCode ierr;
769 
770   PetscFunctionBegin;
771   ierr = PetscViewerCreate(comm,binv);CHKERRQ(ierr);
772   ierr = PetscViewerSetType(*binv,PETSCVIEWERBINARY);CHKERRQ(ierr);
773   ierr = PetscViewerFileSetMode(*binv,type);CHKERRQ(ierr);
774   ierr = PetscViewerFileSetName(*binv,name);CHKERRQ(ierr);
775   ierr = PetscViewerSetFromOptions(*binv);CHKERRQ(ierr);
776   PetscFunctionReturn(0);
777 }
778 
779 #if defined(PETSC_HAVE_MPIIO)
780 static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype,PetscBool write)
781 {
782   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
783   PetscErrorCode     ierr;
784   MPI_Datatype       mdtype;
785   PetscMPIInt        cnt;
786   MPI_Status         status;
787   MPI_Aint           ul,dsize;
788 
789   PetscFunctionBegin;
790   ierr = PetscMPIIntCast(num,&cnt);CHKERRQ(ierr);
791   ierr = PetscDataTypeToMPIDataType(dtype,&mdtype);CHKERRQ(ierr);
792   ierr = MPI_File_set_view(vbinary->mfdes,vbinary->moff,mdtype,mdtype,(char*)"native",MPI_INFO_NULL);CHKERRQ(ierr);
793   if (write) {
794     ierr = MPIU_File_write_all(vbinary->mfdes,data,cnt,mdtype,&status);CHKERRQ(ierr);
795   } else {
796     ierr = MPIU_File_read_all(vbinary->mfdes,data,cnt,mdtype,&status);CHKERRQ(ierr);
797   }
798   ierr = MPI_Type_get_extent(mdtype,&ul,&dsize);CHKERRQ(ierr);
799 
800   vbinary->moff += dsize*cnt;
801   if (count) *count = num;
802   PetscFunctionReturn(0);
803 }
804 #endif
805 
806 /*@C
807    PetscViewerBinaryRead - Reads from a binary file, all processors get the same result
808 
809    Collective on MPI_Comm
810 
811    Input Parameters:
812 +  viewer - the binary viewer
813 .  data - location of the data to be written
814 .  num - number of items of data to read
815 -  dtype - type of data to read
816 
817    Output Parameters:
818 .  count - number of items of data actually read, or NULL. Unless an error is generated this is always set to the input parameter num.
819 
820    Level: beginner
821 
822    Concepts: binary files
823 
824    Developer Note: Since count is always set to num it is not clear what purpose the output argument count serves.
825 
826 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
827           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
828           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
829 @*/
830 PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype)
831 {
832   PetscErrorCode     ierr;
833   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
834 
835   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
836 #if defined(PETSC_HAVE_MPIIO)
837   if (vbinary->usempiio) {
838     ierr = PetscViewerBinaryWriteReadMPIIO(viewer,data,num,count,dtype,PETSC_FALSE);CHKERRQ(ierr);
839   } else {
840 #endif
841     ierr = PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,num,dtype);CHKERRQ(ierr);
842     if (count) *count = num;
843 #if defined(PETSC_HAVE_MPIIO)
844   }
845 #endif
846   PetscFunctionReturn(0);
847 }
848 
849 /*@C
850    PetscViewerBinaryWrite - writes to a binary file, only from the first process
851 
852    Collective on MPI_Comm
853 
854    Input Parameters:
855 +  viewer - the binary viewer
856 .  data - location of data
857 .  count - number of items of data to write
858 .  dtype - type of data to write
859 -  istemp - data may be overwritten
860 
861    Level: beginner
862 
863    Notes: because byte-swapping may be done on the values in data it cannot be declared const
864 
865    Concepts: binary files
866 
867 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
868           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(), PetscDataType
869           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
870 @*/
871 PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype,PetscBool istemp)
872 {
873   PetscErrorCode     ierr;
874   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
875 
876   PetscFunctionBegin;
877   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
878 #if defined(PETSC_HAVE_MPIIO)
879   if (vbinary->usempiio) {
880     ierr = PetscViewerBinaryWriteReadMPIIO(viewer,data,count,NULL,dtype,PETSC_TRUE);CHKERRQ(ierr);
881   } else {
882 #endif
883     ierr = PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype,istemp);CHKERRQ(ierr);
884 #if defined(PETSC_HAVE_MPIIO)
885   }
886 #endif
887   PetscFunctionReturn(0);
888 }
889 
890 /*@C
891    PetscViewerBinaryWriteStringArray - writes to a binary file, only from the first process an array of strings
892 
893    Collective on MPI_Comm
894 
895    Input Parameters:
896 +  viewer - the binary viewer
897 -  data - location of the array of strings
898 
899 
900    Level: intermediate
901 
902    Concepts: binary files
903 
904     Notes: array of strings is null terminated
905 
906 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
907           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
908           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
909 @*/
910 PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer,char **data)
911 {
912   PetscErrorCode ierr;
913   PetscInt       i,n = 0,*sizes;
914 
915   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
916   /* count number of strings */
917   while (data[n++]) ;
918   n--;
919   ierr     = PetscMalloc1(n+1,&sizes);CHKERRQ(ierr);
920   sizes[0] = n;
921   for (i=0; i<n; i++) {
922     size_t tmp;
923     ierr       = PetscStrlen(data[i],&tmp);CHKERRQ(ierr);
924     sizes[i+1] = tmp + 1;   /* size includes space for the null terminator */
925   }
926   ierr = PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
927   for (i=0; i<n; i++) {
928     ierr = PetscViewerBinaryWrite(viewer,data[i],sizes[i+1],PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
929   }
930   ierr = PetscFree(sizes);CHKERRQ(ierr);
931   PetscFunctionReturn(0);
932 }
933 
934 /*@C
935    PetscViewerBinaryReadStringArray - reads a binary file an array of strings
936 
937    Collective on MPI_Comm
938 
939    Input Parameter:
940 .  viewer - the binary viewer
941 
942    Output Parameter:
943 .  data - location of the array of strings
944 
945    Level: intermediate
946 
947    Concepts: binary files
948 
949     Notes: array of strings is null terminated
950 
951 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
952           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
953           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
954 @*/
955 PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
956 {
957   PetscErrorCode ierr;
958   PetscInt       i,n,*sizes,N = 0;
959 
960   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
961   /* count number of strings */
962   ierr = PetscViewerBinaryRead(viewer,&n,1,NULL,PETSC_INT);CHKERRQ(ierr);
963   ierr = PetscMalloc1(n,&sizes);CHKERRQ(ierr);
964   ierr = PetscViewerBinaryRead(viewer,sizes,n,NULL,PETSC_INT);CHKERRQ(ierr);
965   for (i=0; i<n; i++) N += sizes[i];
966   ierr = PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);CHKERRQ(ierr);
967   (*data)[0] = (char*)((*data) + n + 1);
968   for (i=1; i<n; i++) (*data)[i] = (*data)[i-1] + sizes[i-1];
969   ierr = PetscViewerBinaryRead(viewer,(*data)[0],N,NULL,PETSC_CHAR);CHKERRQ(ierr);
970 
971   (*data)[n] = 0;
972 
973   ierr = PetscFree(sizes);CHKERRQ(ierr);
974   PetscFunctionReturn(0);
975 }
976 
977 static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
978 {
979   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
980 
981   PetscFunctionBegin;
982   *name = vbinary->filename;
983   PetscFunctionReturn(0);
984 }
985 
986 /*@C
987      PetscViewerFileGetMode - Gets the type of file to be open
988 
989     Not Collective
990 
991   Input Parameter:
992 .  viewer - the PetscViewer; must be a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
993 
994   Output Parameter:
995 .  type - type of file
996 $    FILE_MODE_WRITE - create new file for binary output
997 $    FILE_MODE_READ - open existing file for binary input
998 $    FILE_MODE_APPEND - open existing file for binary output
999 
1000   Level: advanced
1001 
1002 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
1003 
1004 @*/
1005 PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *type)
1006 {
1007   PetscErrorCode ierr;
1008 
1009   PetscFunctionBegin;
1010   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1011   PetscValidPointer(type,2);
1012   ierr = PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,type));CHKERRQ(ierr);
1013   PetscFunctionReturn(0);
1014 }
1015 
1016 /*@
1017     PetscViewerBinarySetUseMPIIO - Sets a binary viewer to use MPI-IO for reading/writing. Must be called
1018         before PetscViewerFileSetName()
1019 
1020     Logically Collective on PetscViewer
1021 
1022     Input Parameters:
1023 +   viewer - the PetscViewer; must be a binary
1024 -   flg - PETSC_TRUE means MPI-IO will be used
1025 
1026     Options Database:
1027     -viewer_binary_mpiio : Flag for using MPI-IO
1028 
1029     Level: advanced
1030 
1031 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
1032           PetscViewerBinaryGetUseMPIIO()
1033 
1034 @*/
1035 PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool flg)
1036 {
1037   PetscErrorCode ierr;
1038 
1039   PetscFunctionBegin;
1040   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1041   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr);
1042   PetscFunctionReturn(0);
1043 }
1044 
1045 /*@C
1046      PetscViewerFileSetMode - Sets the type of file to be open
1047 
1048     Logically Collective on PetscViewer
1049 
1050   Input Parameters:
1051 +  viewer - the PetscViewer; must be a a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
1052 -  type - type of file
1053 $    FILE_MODE_WRITE - create new file for binary output
1054 $    FILE_MODE_READ - open existing file for binary input
1055 $    FILE_MODE_APPEND - open existing file for binary output
1056 
1057   Level: advanced
1058 
1059 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
1060 
1061 @*/
1062 PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode type)
1063 {
1064   PetscErrorCode ierr;
1065 
1066   PetscFunctionBegin;
1067   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1068   PetscValidLogicalCollectiveEnum(viewer,type,2);
1069   ierr = PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,type));CHKERRQ(ierr);
1070   PetscFunctionReturn(0);
1071 }
1072 
1073 static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *type)
1074 {
1075   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1076 
1077   PetscFunctionBegin;
1078   *type = vbinary->btype;
1079   PetscFunctionReturn(0);
1080 }
1081 
1082 static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode type)
1083 {
1084   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1085 
1086   PetscFunctionBegin;
1087   vbinary->btype = type;
1088   PetscFunctionReturn(0);
1089 }
1090 
1091 static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
1092 {
1093   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1094   PetscErrorCode     ierr;
1095 
1096   PetscFunctionBegin;
1097   if (vbinary->filename) { ierr = PetscFree(vbinary->filename);CHKERRQ(ierr); }
1098   ierr = PetscStrallocpy(name,&vbinary->filename);CHKERRQ(ierr);
1099   PetscFunctionReturn(0);
1100 }
1101 /*
1102         Actually opens the file
1103 */
1104 static PetscErrorCode PetscViewerFileSetUp_Binary(PetscViewer viewer)
1105 {
1106   PetscMPIInt        rank;
1107   PetscErrorCode     ierr;
1108   size_t             len;
1109   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1110   const char         *fname;
1111   char               bname[PETSC_MAX_PATH_LEN],*gz;
1112   PetscBool          found;
1113   PetscFileMode      type = vbinary->btype;
1114 
1115   PetscFunctionBegin;
1116   if (type == (PetscFileMode) -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode()");
1117   if (!vbinary->filename) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetName()");
1118   ierr = PetscViewerFileClose_Binary(viewer);CHKERRQ(ierr);
1119 
1120   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
1121 
1122   /* if ends in .gz strip that off and note user wants file compressed */
1123   vbinary->storecompressed = PETSC_FALSE;
1124   if (!rank && type == FILE_MODE_WRITE) {
1125     /* remove .gz if it ends library name */
1126     ierr = PetscStrstr(vbinary->filename,".gz",&gz);CHKERRQ(ierr);
1127     if (gz) {
1128       ierr = PetscStrlen(gz,&len);CHKERRQ(ierr);
1129       if (len == 3) {
1130         *gz = 0;
1131         vbinary->storecompressed = PETSC_TRUE;
1132       }
1133     }
1134   }
1135 
1136   /* only first processor opens file if writeable */
1137   if (!rank || type == FILE_MODE_READ) {
1138 
1139     if (type == FILE_MODE_READ) {
1140       /* possibly get the file from remote site or compressed file */
1141       ierr  = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1142       fname = bname;
1143       if (!rank && !found) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
1144       else if (!found) {
1145         ierr  = PetscInfo(viewer,"Nonzero processor did not locate readonly file\n");CHKERRQ(ierr);
1146         fname = 0;
1147       }
1148     } else fname = vbinary->filename;
1149 
1150 #if defined(PETSC_HAVE_O_BINARY)
1151     if (type == FILE_MODE_WRITE) {
1152       if ((vbinary->fdes = open(fname,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
1153     } else if (type == FILE_MODE_READ && fname) {
1154       if ((vbinary->fdes = open(fname,O_RDONLY|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
1155     } else if (type == FILE_MODE_APPEND) {
1156       if ((vbinary->fdes = open(fname,O_WRONLY|O_APPEND|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
1157     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1158 #else
1159     if (type == FILE_MODE_WRITE) {
1160       if ((vbinary->fdes = creat(fname,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
1161     } else if (type == FILE_MODE_READ && fname) {
1162       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
1163     } else if (type == FILE_MODE_APPEND) {
1164       if ((vbinary->fdes = open(fname,O_WRONLY|O_APPEND,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
1165     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1166 #endif
1167   } else vbinary->fdes = -1;
1168 
1169   /*
1170       try to open info file: all processors open this file if read only
1171   */
1172   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1173     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];
1174 
1175     ierr = PetscStrcpy(infoname,vbinary->filename);CHKERRQ(ierr);
1176     /* remove .gz if it ends library name */
1177     ierr = PetscStrstr(infoname,".gz",&gz);CHKERRQ(ierr);
1178     if (gz) {
1179       ierr = PetscStrlen(gz,&len);CHKERRQ(ierr);
1180       if (len == 3) *gz = 0;
1181     }
1182 
1183     ierr = PetscStrcat(infoname,".info");CHKERRQ(ierr);
1184     ierr = PetscFixFilename(infoname,iname);CHKERRQ(ierr);
1185     if (type == FILE_MODE_READ) {
1186       ierr = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1187       ierr = PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);CHKERRQ(ierr);
1188     } else {
1189       vbinary->fdes_info = fopen(infoname,"w");
1190       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1191     }
1192   }
1193 #if defined(PETSC_USE_LOG)
1194   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1195 #endif
1196   PetscFunctionReturn(0);
1197 }
1198 
1199 #if defined(PETSC_HAVE_MPIIO)
1200 static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1201 {
1202   PetscMPIInt        rank;
1203   PetscErrorCode     ierr;
1204   size_t             len;
1205   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1206   char               *gz;
1207   PetscBool          found;
1208   PetscFileMode      type = vbinary->btype;
1209 
1210   PetscFunctionBegin;
1211   if (type == (PetscFileMode) -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode()");
1212   if (!vbinary->filename) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetName()");
1213   ierr = PetscViewerFileClose_BinaryMPIIO(viewer);CHKERRQ(ierr);
1214 
1215   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
1216 
1217   vbinary->storecompressed = PETSC_FALSE;
1218 
1219   /* only first processor opens file if writeable */
1220   if (type == FILE_MODE_READ) {
1221     MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,MPI_MODE_RDONLY,MPI_INFO_NULL,&vbinary->mfdes);CHKERRQ(ierr);
1222   } else if (type == FILE_MODE_WRITE) {
1223     MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,MPI_MODE_WRONLY | MPI_MODE_CREATE,MPI_INFO_NULL,&vbinary->mfdes);CHKERRQ(ierr);
1224   }
1225 
1226   /*
1227       try to open info file: all processors open this file if read only
1228 
1229       Below is identical code to the code for Binary above, should be put in separate routine
1230   */
1231   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1232     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];
1233 
1234     ierr = PetscStrcpy(infoname,vbinary->filename);CHKERRQ(ierr);
1235     /* remove .gz if it ends library name */
1236     ierr = PetscStrstr(infoname,".gz",&gz);CHKERRQ(ierr);
1237     if (gz) {
1238       ierr = PetscStrlen(gz,&len);CHKERRQ(ierr);
1239       if (len == 3) *gz = 0;
1240     }
1241 
1242     ierr = PetscStrcat(infoname,".info");CHKERRQ(ierr);
1243     ierr = PetscFixFilename(infoname,iname);CHKERRQ(ierr);
1244     if (type == FILE_MODE_READ) {
1245       ierr = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1246       ierr = PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);CHKERRQ(ierr);
1247     } else {
1248       vbinary->fdes_info = fopen(infoname,"w");
1249       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1250     }
1251   }
1252 #if defined(PETSC_USE_LOG)
1253   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1254 #endif
1255   PetscFunctionReturn(0);
1256 }
1257 
1258 static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool flg)
1259 {
1260   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1261   PetscFunctionBegin;
1262   vbinary->usempiio = flg;
1263   PetscFunctionReturn(0);
1264 }
1265 #endif
1266 
1267 static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
1268 {
1269   PetscErrorCode     ierr;
1270   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1271 
1272   PetscFunctionBegin;
1273   if (binary->filename) {
1274     ierr = PetscViewerASCIIPrintf(viewer,"Filename: %s\n",binary->filename);CHKERRQ(ierr);
1275   }
1276   PetscFunctionReturn(0);
1277 }
1278 
1279 static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer v)
1280 {
1281   PetscErrorCode     ierr;
1282   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1283 
1284   PetscFunctionBegin;
1285   if (!binary->setfromoptionscalled) { ierr = PetscViewerSetFromOptions(v);CHKERRQ(ierr); }
1286 
1287 #if defined(PETSC_HAVE_MPIIO)
1288   if (binary->usempiio) {
1289     ierr = PetscViewerFileSetUp_BinaryMPIIO(v);CHKERRQ(ierr);
1290   } else {
1291 #endif
1292     ierr = PetscViewerFileSetUp_Binary(v);CHKERRQ(ierr);
1293 #if defined(PETSC_HAVE_MPIIO)
1294   }
1295 #endif
1296   PetscFunctionReturn(0);
1297 }
1298 
1299 static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer v)
1300 {
1301   PetscErrorCode     ierr;
1302   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1303   char               defaultname[PETSC_MAX_PATH_LEN];
1304   PetscBool          flg;
1305 
1306   PetscFunctionBegin;
1307   ierr = PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");CHKERRQ(ierr);
1308   ierr = PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");CHKERRQ(ierr);
1309   ierr = PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,PETSC_MAX_PATH_LEN-1,&flg);CHKERRQ(ierr);
1310   if (flg) { ierr = PetscViewerFileSetName_Binary(v,defaultname);CHKERRQ(ierr); }
1311   ierr = PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",PETSC_FALSE,&binary->skipinfo,NULL);CHKERRQ(ierr);
1312   ierr = PetscOptionsBool("-viewer_binary_skip_options","Skip parsing vec load options","PetscViewerBinarySetSkipOptions",PETSC_TRUE,&binary->skipoptions,NULL);CHKERRQ(ierr);
1313   ierr = PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",PETSC_FALSE,&binary->skipheader,NULL);CHKERRQ(ierr);
1314 #if defined(PETSC_HAVE_MPIIO)
1315   ierr = PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,&binary->usempiio,NULL);CHKERRQ(ierr);
1316 #elif defined(PETSC_HAVE_MPIUNI)
1317   ierr = PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL);CHKERRQ(ierr);
1318 #endif
1319   ierr = PetscOptionsTail();CHKERRQ(ierr);
1320   binary->setfromoptionscalled = PETSC_TRUE;
1321   PetscFunctionReturn(0);
1322 }
1323 
1324 /*MC
1325    PETSCVIEWERBINARY - A viewer that saves to binary files
1326 
1327 
1328 .seealso:  PetscViewerBinaryOpen(), PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD, PetscViewerCreate(), PetscViewerASCIIOpen(),
1329            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, PETSCVIEWERDRAW,
1330            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType(),
1331            PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO()
1332 
1333   Level: beginner
1334 
1335 M*/
1336 
1337 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1338 {
1339   PetscErrorCode     ierr;
1340   PetscViewer_Binary *vbinary;
1341 
1342   PetscFunctionBegin;
1343   ierr                     = PetscNewLog(v,&vbinary);CHKERRQ(ierr);
1344   v->data                  = (void*)vbinary;
1345   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
1346   v->ops->destroy          = PetscViewerDestroy_Binary;
1347   v->ops->view             = PetscViewerView_Binary;
1348   v->ops->setup            = PetscViewerSetUp_Binary;
1349   v->ops->flush            = NULL;
1350   vbinary->fdes_info       = 0;
1351   vbinary->fdes            = 0;
1352   vbinary->skipinfo        = PETSC_FALSE;
1353   vbinary->skipoptions     = PETSC_TRUE;
1354   vbinary->skipheader      = PETSC_FALSE;
1355   vbinary->setfromoptionscalled = PETSC_FALSE;
1356   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
1357   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1358   v->ops->read             = PetscViewerBinaryRead;
1359   vbinary->btype           = (PetscFileMode) -1;
1360   vbinary->storecompressed = PETSC_FALSE;
1361   vbinary->filename        = 0;
1362   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */
1363 
1364   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary);CHKERRQ(ierr);
1365   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary);CHKERRQ(ierr);
1366   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary);CHKERRQ(ierr);
1367   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary);CHKERRQ(ierr);
1368   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",PetscViewerBinaryGetSkipOptions_Binary);CHKERRQ(ierr);
1369   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",PetscViewerBinarySetSkipOptions_Binary);CHKERRQ(ierr);
1370   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",PetscViewerBinaryGetSkipInfo_Binary);CHKERRQ(ierr);
1371   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",PetscViewerBinarySetSkipInfo_Binary);CHKERRQ(ierr);
1372   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary);CHKERRQ(ierr);
1373   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary);CHKERRQ(ierr);
1374   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary);CHKERRQ(ierr);
1375   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary);CHKERRQ(ierr);
1376   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary);CHKERRQ(ierr);
1377 #if defined(PETSC_HAVE_MPIIO)
1378   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",PetscViewerBinaryGetUseMPIIO_Binary);CHKERRQ(ierr);
1379   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",PetscViewerBinarySetUseMPIIO_Binary);CHKERRQ(ierr);
1380 #endif
1381   PetscFunctionReturn(0);
1382 }
1383 
1384 /* ---------------------------------------------------------------------*/
1385 /*
1386     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1387   is attached to a communicator, in this case the attribute is a PetscViewer.
1388 */
1389 static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
1390 
1391 /*@C
1392      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
1393                      in a communicator.
1394 
1395      Collective on MPI_Comm
1396 
1397      Input Parameter:
1398 .    comm - the MPI communicator to share the binary PetscViewer
1399 
1400      Level: intermediate
1401 
1402    Options Database Keys:
1403 +    -viewer_binary_filename <name>
1404 .    -viewer_binary_skip_info
1405 .    -viewer_binary_skip_options
1406 .    -viewer_binary_skip_header
1407 -    -viewer_binary_mpiio
1408 
1409    Environmental variables:
1410 -   PETSC_VIEWER_BINARY_FILENAME
1411 
1412      Notes:
1413      Unlike almost all other PETSc routines, PETSC_VIEWER_BINARY_ does not return
1414      an error code.  The binary PetscViewer is usually used in the form
1415 $       XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));
1416 
1417 .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
1418           PetscViewerDestroy()
1419 @*/
1420 PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1421 {
1422   PetscErrorCode ierr;
1423   PetscBool      flg;
1424   PetscViewer    viewer;
1425   char           fname[PETSC_MAX_PATH_LEN];
1426   MPI_Comm       ncomm;
1427 
1428   PetscFunctionBegin;
1429   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1430   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1431     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
1432     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1433   }
1434   ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
1435   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1436   if (!flg) { /* PetscViewer not yet created */
1437     ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1438     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1439     if (!flg) {
1440       ierr = PetscStrcpy(fname,"binaryoutput");
1441       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1442     }
1443     ierr = PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
1444     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1445     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
1446     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1447     ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
1448     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1449   }
1450   ierr = PetscCommDestroy(&ncomm);
1451   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
1452   PetscFunctionReturn(viewer);
1453 }
1454