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