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