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