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