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