xref: /petsc/src/sys/classes/viewer/impls/binary/binv.c (revision ae3c970873064af5814da0b2071ef005eed1aebf)
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 -  istemp - data may be overwritten
938 
939    Level: beginner
940 
941    Notes:
942     because byte-swapping may be done on the values in data it cannot be declared const
943 
944 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
945           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(), PetscDataType
946           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
947 @*/
948 PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype,PetscBool istemp)
949 {
950   PetscErrorCode     ierr;
951   PetscViewer_Binary *vbinary;
952 
953   PetscFunctionBegin;
954   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
955   PetscValidLogicalCollectiveInt(viewer,count,3);
956   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
957   vbinary = (PetscViewer_Binary*)viewer->data;
958 #if defined(PETSC_HAVE_MPIIO)
959   if (vbinary->usempiio) {
960     ierr = PetscViewerBinaryWriteReadMPIIO(viewer,data,count,NULL,dtype,PETSC_TRUE);CHKERRQ(ierr);
961   } else {
962 #endif
963     ierr = PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype,istemp);CHKERRQ(ierr);
964 #if defined(PETSC_HAVE_MPIIO)
965   }
966 #endif
967   PetscFunctionReturn(0);
968 }
969 
970 /*@C
971    PetscViewerBinaryWriteStringArray - writes to a binary file, only from the first process an array of strings
972 
973    Collective
974 
975    Input Parameters:
976 +  viewer - the binary viewer
977 -  data - location of the array of strings
978 
979 
980    Level: intermediate
981 
982     Notes:
983     array of strings is null terminated
984 
985 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
986           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
987           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
988 @*/
989 PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer,const char * const *data)
990 {
991   PetscErrorCode ierr;
992   PetscInt       i,n = 0,*sizes;
993 
994   PetscFunctionBegin;
995   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
996   /* count number of strings */
997   while (data[n++]) ;
998   n--;
999   ierr     = PetscMalloc1(n+1,&sizes);CHKERRQ(ierr);
1000   sizes[0] = n;
1001   for (i=0; i<n; i++) {
1002     size_t tmp;
1003     ierr       = PetscStrlen(data[i],&tmp);CHKERRQ(ierr);
1004     sizes[i+1] = tmp + 1;   /* size includes space for the null terminator */
1005   }
1006   ierr = PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
1007   for (i=0; i<n; i++) {
1008     ierr = PetscViewerBinaryWrite(viewer,(void*)data[i],sizes[i+1],PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
1009   }
1010   ierr = PetscFree(sizes);CHKERRQ(ierr);
1011   PetscFunctionReturn(0);
1012 }
1013 
1014 /*@C
1015    PetscViewerBinaryReadStringArray - reads a binary file an array of strings
1016 
1017    Collective
1018 
1019    Input Parameter:
1020 .  viewer - the binary viewer
1021 
1022    Output Parameter:
1023 .  data - location of the array of strings
1024 
1025    Level: intermediate
1026 
1027     Notes:
1028     array of strings is null terminated
1029 
1030 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
1031           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
1032           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
1033 @*/
1034 PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
1035 {
1036   PetscErrorCode ierr;
1037   PetscInt       i,n,*sizes,N = 0;
1038 
1039   PetscFunctionBegin;
1040   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1041   /* count number of strings */
1042   ierr = PetscViewerBinaryRead(viewer,&n,1,NULL,PETSC_INT);CHKERRQ(ierr);
1043   ierr = PetscMalloc1(n,&sizes);CHKERRQ(ierr);
1044   ierr = PetscViewerBinaryRead(viewer,sizes,n,NULL,PETSC_INT);CHKERRQ(ierr);
1045   for (i=0; i<n; i++) N += sizes[i];
1046   ierr = PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);CHKERRQ(ierr);
1047   (*data)[0] = (char*)((*data) + n + 1);
1048   for (i=1; i<n; i++) (*data)[i] = (*data)[i-1] + sizes[i-1];
1049   ierr = PetscViewerBinaryRead(viewer,(*data)[0],N,NULL,PETSC_CHAR);CHKERRQ(ierr);
1050 
1051   (*data)[n] = NULL;
1052 
1053   ierr = PetscFree(sizes);CHKERRQ(ierr);
1054   PetscFunctionReturn(0);
1055 }
1056 
1057 static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
1058 {
1059   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1060 
1061   PetscFunctionBegin;
1062   *name = vbinary->filename;
1063   PetscFunctionReturn(0);
1064 }
1065 
1066 /*@C
1067      PetscViewerFileGetMode - Gets the type of file to be open
1068 
1069     Not Collective
1070 
1071   Input Parameter:
1072 .  viewer - the PetscViewer; must be a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
1073 
1074   Output Parameter:
1075 .  type - type of file
1076 $    FILE_MODE_WRITE - create new file for binary output
1077 $    FILE_MODE_READ - open existing file for binary input
1078 $    FILE_MODE_APPEND - open existing file for binary output
1079 
1080   Level: advanced
1081 
1082 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
1083 
1084 @*/
1085 PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *type)
1086 {
1087   PetscErrorCode ierr;
1088 
1089   PetscFunctionBegin;
1090   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1091   PetscValidPointer(type,2);
1092   ierr = PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,type));CHKERRQ(ierr);
1093   PetscFunctionReturn(0);
1094 }
1095 
1096 /*@
1097     PetscViewerBinarySetUseMPIIO - Sets a binary viewer to use MPI-IO for reading/writing. Must be called
1098         before PetscViewerFileSetName()
1099 
1100     Logically Collective on PetscViewer
1101 
1102     Input Parameters:
1103 +   viewer - the PetscViewer; must be a binary
1104 -   flg - PETSC_TRUE means MPI-IO will be used
1105 
1106     Options Database:
1107     -viewer_binary_mpiio : Flag for using MPI-IO
1108 
1109     Level: advanced
1110 
1111 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
1112           PetscViewerBinaryGetUseMPIIO()
1113 
1114 @*/
1115 PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool flg)
1116 {
1117   PetscErrorCode ierr;
1118 
1119   PetscFunctionBegin;
1120   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1121   PetscValidLogicalCollectiveBool(viewer,flg,2);
1122   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr);
1123   PetscFunctionReturn(0);
1124 }
1125 
1126 /*@C
1127      PetscViewerFileSetMode - Sets the type of file to be open
1128 
1129     Logically Collective on PetscViewer
1130 
1131   Input Parameters:
1132 +  viewer - the PetscViewer; must be a a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
1133 -  type - type of file
1134 $    FILE_MODE_WRITE - create new file for output
1135 $    FILE_MODE_READ - open existing file for input
1136 $    FILE_MODE_APPEND - open existing file for output
1137 
1138   Level: advanced
1139 
1140 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
1141 
1142 @*/
1143 PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode type)
1144 {
1145   PetscErrorCode ierr;
1146 
1147   PetscFunctionBegin;
1148   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1149   PetscValidLogicalCollectiveEnum(viewer,type,2);
1150   ierr = PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,type));CHKERRQ(ierr);
1151   PetscFunctionReturn(0);
1152 }
1153 
1154 static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *type)
1155 {
1156   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1157 
1158   PetscFunctionBegin;
1159   *type = vbinary->btype;
1160   PetscFunctionReturn(0);
1161 }
1162 
1163 static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode type)
1164 {
1165   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1166 
1167   PetscFunctionBegin;
1168   if (viewer->setupcalled && vbinary->btype != type) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER,"Cannot change mode to %s after setup",PetscFileModes[type]);
1169   vbinary->btype = type;
1170   PetscFunctionReturn(0);
1171 }
1172 
1173 static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
1174 {
1175   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1176   PetscErrorCode     ierr;
1177 
1178   PetscFunctionBegin;
1179   if (vbinary->filename) {
1180     /* gzip can be run after the file with the previous filename has been closed */
1181     ierr = PetscFree(vbinary->ogzfilename);CHKERRQ(ierr);
1182     ierr = PetscStrallocpy(vbinary->filename,&vbinary->ogzfilename);CHKERRQ(ierr);
1183     ierr = PetscFree(vbinary->filename);CHKERRQ(ierr);
1184     viewer->setupcalled = PETSC_FALSE;
1185   }
1186   ierr = PetscStrallocpy(name,&vbinary->filename);CHKERRQ(ierr);
1187   PetscFunctionReturn(0);
1188 }
1189 /*
1190         Actually opens the file
1191 */
1192 static PetscErrorCode PetscViewerFileSetUp_Binary(PetscViewer viewer)
1193 {
1194   PetscMPIInt        rank;
1195   PetscErrorCode     ierr;
1196   size_t             len;
1197   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1198   const char         *fname;
1199   char               bname[PETSC_MAX_PATH_LEN],*gz;
1200   PetscBool          found;
1201   PetscFileMode      type = vbinary->btype;
1202 
1203   PetscFunctionBegin;
1204   if (type == (PetscFileMode) -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode()");
1205   if (!vbinary->filename) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetName()");
1206   ierr = PetscViewerFileClose_Binary(viewer);CHKERRQ(ierr);
1207 
1208   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
1209 
1210   /* if ends in .gz strip that off and note user wants file compressed */
1211   vbinary->storecompressed = PETSC_FALSE;
1212   if (!rank && type == FILE_MODE_WRITE) {
1213     /* remove .gz if it ends library name */
1214     ierr = PetscStrstr(vbinary->filename,".gz",&gz);CHKERRQ(ierr);
1215     if (gz) {
1216       ierr = PetscStrlen(gz,&len);CHKERRQ(ierr);
1217       if (len == 3) {
1218         *gz = 0;
1219         vbinary->storecompressed = PETSC_TRUE;
1220       }
1221     }
1222   }
1223 
1224   /* only first processor opens file if writeable */
1225   if (!rank || type == FILE_MODE_READ) {
1226 
1227     if (type == FILE_MODE_READ) {
1228       /* possibly get the file from remote site or compressed file */
1229       ierr  = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1230       fname = bname;
1231       /* comm below may be global as all ranks go here for FILE_MODE_READ and output 'found' of PetscFileRetrieve() is valid on all processes */
1232       if (!found) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
1233     } else fname = vbinary->filename;
1234     if (type == FILE_MODE_APPEND) { /* check if asked to append to a non-existing file */
1235       ierr = PetscTestFile(fname,'\0',&found);CHKERRQ(ierr);
1236     }
1237 
1238 #if defined(PETSC_HAVE_O_BINARY)
1239     if (type == FILE_MODE_WRITE || (type == FILE_MODE_APPEND && !found) ) {
1240       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);
1241     } else if (type == FILE_MODE_READ && fname) {
1242       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);
1243     } else if (type == FILE_MODE_APPEND) {
1244       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);
1245     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1246 #else
1247     if (type == FILE_MODE_WRITE || (type == FILE_MODE_APPEND && !found) ) {
1248       if ((vbinary->fdes = creat(fname,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
1249     } else if (type == FILE_MODE_READ && fname) {
1250       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
1251     } else if (type == FILE_MODE_APPEND) {
1252       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);
1253     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1254 #endif
1255   } else vbinary->fdes = -1;
1256 
1257   /*
1258       try to open info file: all processors open this file if read only
1259   */
1260   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1261     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];
1262 
1263     ierr = PetscStrncpy(infoname,vbinary->filename,sizeof(infoname));CHKERRQ(ierr);
1264     /* remove .gz if it ends library name */
1265     ierr = PetscStrstr(infoname,".gz",&gz);CHKERRQ(ierr);
1266     if (gz) {
1267       ierr = PetscStrlen(gz,&len);CHKERRQ(ierr);
1268       if (len == 3) *gz = 0;
1269     }
1270 
1271     ierr = PetscStrlcat(infoname,".info",sizeof(infoname));CHKERRQ(ierr);
1272     ierr = PetscFixFilename(infoname,iname);CHKERRQ(ierr);
1273     if (type == FILE_MODE_READ) {
1274       ierr = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1275       if (found) {
1276         ierr = PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);CHKERRQ(ierr);
1277       }
1278     } else {
1279       vbinary->fdes_info = fopen(infoname,"w");
1280       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1281     }
1282   }
1283 #if defined(PETSC_USE_LOG)
1284   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1285 #endif
1286   PetscFunctionReturn(0);
1287 }
1288 
1289 #if defined(PETSC_HAVE_MPIIO)
1290 static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1291 {
1292   PetscMPIInt        rank;
1293   PetscErrorCode     ierr;
1294   size_t             len;
1295   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1296   char               *gz;
1297   PetscBool          found;
1298   PetscFileMode      type = vbinary->btype;
1299   int                amode;
1300 
1301   PetscFunctionBegin;
1302   if (type == (PetscFileMode) -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode()");
1303   if (!vbinary->filename) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetName()");
1304   ierr = PetscViewerFileClose_BinaryMPIIO(viewer);CHKERRQ(ierr);
1305 
1306   vbinary->storecompressed = PETSC_FALSE;
1307 
1308   switch (type) {
1309   case FILE_MODE_READ:   amode = MPI_MODE_RDONLY; break;
1310   case FILE_MODE_WRITE:  amode = MPI_MODE_WRONLY | MPI_MODE_CREATE; break;
1311   case FILE_MODE_APPEND: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_APPEND; break;
1312   default: SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[type]);
1313   }
1314   ierr = MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfdes);CHKERRQ(ierr);
1315   /*
1316       The MPI standard does not have MPI_MODE_TRUNCATE. We emulate this behavior by setting the file size to zero.
1317   */
1318   if (type == FILE_MODE_WRITE) {ierr = MPI_File_set_size(vbinary->mfdes,0);CHKERRQ(ierr);}
1319   /*
1320       Initially, all processes view the file as a linear byte stream. Therefore, for files opened with MPI_MODE_APPEND,
1321       MPI_File_get_position[_shared](fh, &offset) returns the absolute byte position at the end of file.
1322       Otherwise, we would need to call MPI_File_get_byte_offset(fh, offset, &byte_offset) to convert
1323       the offset in etype units to an absolute byte position.
1324    */
1325   if (type == FILE_MODE_APPEND) {ierr = MPI_File_get_position(vbinary->mfdes,&vbinary->moff);CHKERRQ(ierr);}
1326 
1327   /*
1328       try to open info file: all processors open this file if read only
1329 
1330       Below is identical code to the code for Binary above, should be put in separate routine
1331   */
1332   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
1333   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1334     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];
1335 
1336     ierr = PetscStrncpy(infoname,vbinary->filename,sizeof(infoname));CHKERRQ(ierr);
1337     /* remove .gz if it ends library name */
1338     ierr = PetscStrstr(infoname,".gz",&gz);CHKERRQ(ierr);
1339     if (gz) {
1340       ierr = PetscStrlen(gz,&len);CHKERRQ(ierr);
1341       if (len == 3) *gz = 0;
1342     }
1343 
1344     ierr = PetscStrlcat(infoname,".info",sizeof(infoname));CHKERRQ(ierr);
1345     ierr = PetscFixFilename(infoname,iname);CHKERRQ(ierr);
1346     if (type == FILE_MODE_READ) {
1347       ierr = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1348       ierr = PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);CHKERRQ(ierr);
1349     } else {
1350       vbinary->fdes_info = fopen(infoname,"w");
1351       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1352     }
1353   }
1354 #if defined(PETSC_USE_LOG)
1355   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1356 #endif
1357   PetscFunctionReturn(0);
1358 }
1359 
1360 static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool flg)
1361 {
1362   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1363   PetscFunctionBegin;
1364   if (viewer->setupcalled && vbinary->usempiio != flg) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER,"Cannot change MPIIO to %s after setup",PetscBools[flg]);
1365   vbinary->usempiio = flg;
1366   PetscFunctionReturn(0);
1367 }
1368 #endif
1369 
1370 static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
1371 {
1372   PetscErrorCode     ierr;
1373   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1374 
1375   PetscFunctionBegin;
1376   if (binary->filename) {
1377     ierr = PetscViewerASCIIPrintf(viewer,"Filename: %s\n",binary->filename);CHKERRQ(ierr);
1378   }
1379   PetscFunctionReturn(0);
1380 }
1381 
1382 static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer v)
1383 {
1384   PetscErrorCode     ierr;
1385   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1386 
1387   PetscFunctionBegin;
1388   if (!binary->setfromoptionscalled) { ierr = PetscViewerSetFromOptions(v);CHKERRQ(ierr); }
1389 
1390 #if defined(PETSC_HAVE_MPIIO)
1391   if (binary->usempiio) {
1392     ierr = PetscViewerFileSetUp_BinaryMPIIO(v);CHKERRQ(ierr);
1393   } else {
1394 #endif
1395     ierr = PetscViewerFileSetUp_Binary(v);CHKERRQ(ierr);
1396 #if defined(PETSC_HAVE_MPIIO)
1397   }
1398 #endif
1399   PetscFunctionReturn(0);
1400 }
1401 
1402 static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer viewer)
1403 {
1404   PetscErrorCode     ierr;
1405   PetscViewer_Binary *binary = (PetscViewer_Binary*)viewer->data;
1406   char               defaultname[PETSC_MAX_PATH_LEN];
1407   PetscBool          flg;
1408 
1409   PetscFunctionBegin;
1410   if (viewer->setupcalled) PetscFunctionReturn(0);
1411   ierr = PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");CHKERRQ(ierr);
1412   ierr = PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");CHKERRQ(ierr);
1413   ierr = PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,PETSC_MAX_PATH_LEN-1,&flg);CHKERRQ(ierr);
1414   if (flg) { ierr = PetscViewerFileSetName_Binary(viewer,defaultname);CHKERRQ(ierr); }
1415   ierr = PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",binary->skipinfo,&binary->skipinfo,NULL);CHKERRQ(ierr);
1416   ierr = PetscOptionsBool("-viewer_binary_skip_options","Skip parsing vec load options","PetscViewerBinarySetSkipOptions",binary->skipoptions,&binary->skipoptions,NULL);CHKERRQ(ierr);
1417   ierr = PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",binary->skipheader,&binary->skipheader,NULL);CHKERRQ(ierr);
1418 #if defined(PETSC_HAVE_MPIIO)
1419   ierr = PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",binary->usempiio,&binary->usempiio,NULL);CHKERRQ(ierr);
1420 #elif defined(PETSC_HAVE_MPIUNI)
1421   ierr = PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL);CHKERRQ(ierr);
1422 #endif
1423   ierr = PetscOptionsTail();CHKERRQ(ierr);
1424   binary->setfromoptionscalled = PETSC_TRUE;
1425   PetscFunctionReturn(0);
1426 }
1427 
1428 /*MC
1429    PETSCVIEWERBINARY - A viewer that saves to binary files
1430 
1431 
1432 .seealso:  PetscViewerBinaryOpen(), PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD, PetscViewerCreate(), PetscViewerASCIIOpen(),
1433            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, PETSCVIEWERDRAW,
1434            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType(),
1435            PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO()
1436 
1437   Level: beginner
1438 
1439 M*/
1440 
1441 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1442 {
1443   PetscErrorCode     ierr;
1444   PetscViewer_Binary *vbinary;
1445 
1446   PetscFunctionBegin;
1447   ierr                     = PetscNewLog(v,&vbinary);CHKERRQ(ierr);
1448   v->data                  = (void*)vbinary;
1449   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
1450   v->ops->destroy          = PetscViewerDestroy_Binary;
1451   v->ops->view             = PetscViewerView_Binary;
1452   v->ops->setup            = PetscViewerSetUp_Binary;
1453   v->ops->flush            = NULL;
1454   vbinary->fdes            = 0;
1455 #if defined(PETSC_HAVE_MPIIO)
1456   vbinary->mfdes           = MPI_FILE_NULL;
1457   vbinary->mfsub           = MPI_FILE_NULL;
1458 #endif
1459   vbinary->fdes_info       = NULL;
1460   vbinary->skipinfo        = PETSC_FALSE;
1461   vbinary->skipoptions     = PETSC_TRUE;
1462   vbinary->skipheader      = PETSC_FALSE;
1463   vbinary->setfromoptionscalled = PETSC_FALSE;
1464   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
1465   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1466   v->ops->read             = PetscViewerBinaryRead;
1467   vbinary->btype           = (PetscFileMode) -1;
1468   vbinary->storecompressed = PETSC_FALSE;
1469   vbinary->filename        = NULL;
1470   vbinary->ogzfilename     = NULL;
1471   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */
1472 
1473   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary);CHKERRQ(ierr);
1474   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary);CHKERRQ(ierr);
1475   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary);CHKERRQ(ierr);
1476   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary);CHKERRQ(ierr);
1477   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",PetscViewerBinaryGetSkipOptions_Binary);CHKERRQ(ierr);
1478   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",PetscViewerBinarySetSkipOptions_Binary);CHKERRQ(ierr);
1479   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",PetscViewerBinaryGetSkipInfo_Binary);CHKERRQ(ierr);
1480   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",PetscViewerBinarySetSkipInfo_Binary);CHKERRQ(ierr);
1481   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary);CHKERRQ(ierr);
1482   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary);CHKERRQ(ierr);
1483   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary);CHKERRQ(ierr);
1484   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary);CHKERRQ(ierr);
1485   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary);CHKERRQ(ierr);
1486 #if defined(PETSC_HAVE_MPIIO)
1487   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",PetscViewerBinaryGetUseMPIIO_Binary);CHKERRQ(ierr);
1488   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",PetscViewerBinarySetUseMPIIO_Binary);CHKERRQ(ierr);
1489 #endif
1490   PetscFunctionReturn(0);
1491 }
1492 
1493 /* ---------------------------------------------------------------------*/
1494 /*
1495     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1496   is attached to a communicator, in this case the attribute is a PetscViewer.
1497 */
1498 PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
1499 
1500 /*@C
1501      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
1502                      in a communicator.
1503 
1504      Collective
1505 
1506      Input Parameter:
1507 .    comm - the MPI communicator to share the binary PetscViewer
1508 
1509      Level: intermediate
1510 
1511    Options Database Keys:
1512 +    -viewer_binary_filename <name>
1513 .    -viewer_binary_skip_info
1514 .    -viewer_binary_skip_options
1515 .    -viewer_binary_skip_header
1516 -    -viewer_binary_mpiio
1517 
1518    Environmental variables:
1519 -   PETSC_VIEWER_BINARY_FILENAME
1520 
1521      Notes:
1522      Unlike almost all other PETSc routines, PETSC_VIEWER_BINARY_ does not return
1523      an error code.  The binary PetscViewer is usually used in the form
1524 $       XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));
1525 
1526 .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
1527           PetscViewerDestroy()
1528 @*/
1529 PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1530 {
1531   PetscErrorCode ierr;
1532   PetscBool      flg;
1533   PetscViewer    viewer;
1534   char           fname[PETSC_MAX_PATH_LEN];
1535   MPI_Comm       ncomm;
1536 
1537   PetscFunctionBegin;
1538   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1539   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1540     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,NULL);
1541     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1542   }
1543   ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
1544   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1545   if (!flg) { /* PetscViewer not yet created */
1546     ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1547     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1548     if (!flg) {
1549       ierr = PetscStrcpy(fname,"binaryoutput");
1550       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1551     }
1552     ierr = PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
1553     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1554     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
1555     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1556     ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
1557     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1558   }
1559   ierr = PetscCommDestroy(&ncomm);
1560   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1561   PetscFunctionReturn(viewer);
1562 }
1563