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