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