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