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