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