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