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