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