xref: /petsc/src/sys/classes/viewer/impls/binary/binv.c (revision 2fa40bb9206b96114faa7cb222621ec184d31cd2)
1 #include <petsc/private/viewerimpl.h>    /*I   "petscviewer.h"   I*/
2 
3 typedef struct  {
4   int           fdes;                 /* file descriptor, ignored if using MPI IO */
5 #if defined(PETSC_HAVE_MPIIO)
6   PetscBool     usempiio;
7   MPI_File      mfdes;                /* ignored unless using MPI IO */
8   MPI_File      mfsub;                /* subviewer support */
9   MPI_Offset    moff;
10 #endif
11   char          *filename;            /* file name */
12   PetscFileMode filemode;             /* read/write/append mode */
13   FILE          *fdes_info;           /* optional file containing info on binary file*/
14   PetscBool     storecompressed;      /* gzip the write binary file when closing it*/
15   char          *ogzfilename;         /* gzip can be run after the filename has been updated */
16   PetscBool     skipinfo;             /* Don't create info file for writing; don't use for reading */
17   PetscBool     skipoptions;          /* don't use PETSc options database when loading */
18   PetscInt      flowcontrol;          /* allow only <flowcontrol> messages outstanding at a time while doing IO */
19   PetscBool     skipheader;           /* don't write header, only raw data */
20   PetscBool     matlabheaderwritten;  /* if format is PETSC_VIEWER_BINARY_MATLAB has the MATLAB .info header been written yet */
21   PetscBool     setfromoptionscalled;
22 } PetscViewer_Binary;
23 
24 #if defined(PETSC_HAVE_MPIIO)
25 static PetscErrorCode PetscViewerBinarySyncMPIIO(PetscViewer viewer)
26 {
27   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
28   PetscErrorCode     ierr;
29 
30   PetscFunctionBegin;
31   if (vbinary->filemode == FILE_MODE_READ) PetscFunctionReturn(0);
32   if (vbinary->mfsub != MPI_FILE_NULL) {
33     ierr = MPI_File_sync(vbinary->mfsub);CHKERRMPI(ierr);
34   }
35   if (vbinary->mfdes != MPI_FILE_NULL) {
36     ierr = MPI_Barrier(PetscObjectComm((PetscObject)viewer));CHKERRMPI(ierr);
37     ierr = MPI_File_sync(vbinary->mfdes);CHKERRMPI(ierr);
38   }
39   PetscFunctionReturn(0);
40 }
41 #endif
42 
43 static PetscErrorCode PetscViewerGetSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
44 {
45   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
46   PetscMPIInt        rank;
47   PetscErrorCode     ierr;
48 
49   PetscFunctionBegin;
50   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
51 
52   /* Return subviewer in process zero */
53   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRMPI(ierr);
54   if (rank == 0) {
55     PetscMPIInt flg;
56 
57     ierr = MPI_Comm_compare(PETSC_COMM_SELF,comm,&flg);CHKERRMPI(ierr);
58     if (flg != MPI_IDENT && flg != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscViewerGetSubViewer() for PETSCVIEWERBINARY requires a singleton MPI_Comm");
59     ierr = PetscViewerCreate(comm,outviewer);CHKERRQ(ierr);
60     ierr = PetscViewerSetType(*outviewer,PETSCVIEWERBINARY);CHKERRQ(ierr);
61     ierr = PetscMemcpy((*outviewer)->data,vbinary,sizeof(PetscViewer_Binary));CHKERRQ(ierr);
62     (*outviewer)->setupcalled = PETSC_TRUE;
63   } else {
64     *outviewer = NULL;
65   }
66 
67 #if defined(PETSC_HAVE_MPIIO)
68   if (vbinary->usempiio && *outviewer) {
69     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
70     /* Parent viewer opens a new MPI file handle on PETSC_COMM_SELF and keeps track of it for future reuse */
71     if (vbinary->mfsub == MPI_FILE_NULL) {
72       int amode;
73       switch (vbinary->filemode) {
74       case FILE_MODE_READ:   amode = MPI_MODE_RDONLY; break;
75       case FILE_MODE_WRITE:  amode = MPI_MODE_WRONLY; break;
76       case FILE_MODE_APPEND: amode = MPI_MODE_WRONLY; break;
77       default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[vbinary->filemode]);
78       }
79       ierr = MPI_File_open(PETSC_COMM_SELF,vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfsub);CHKERRMPI(ierr);
80     }
81     /* Subviewer gets the MPI file handle on PETSC_COMM_SELF */
82     obinary->mfdes = vbinary->mfsub;
83     obinary->mfsub = MPI_FILE_NULL;
84     obinary->moff  = vbinary->moff;
85   }
86 #endif
87 
88 #if defined(PETSC_HAVE_MPIIO)
89   ierr = PetscViewerBinarySyncMPIIO(viewer);CHKERRQ(ierr);
90 #endif
91   PetscFunctionReturn(0);
92 }
93 
94 static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
95 {
96   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
97   PetscMPIInt        rank;
98   PetscErrorCode     ierr;
99 #if defined(PETSC_HAVE_MPIIO)
100   MPI_Offset         moff = 0;
101 #endif
102 
103   PetscFunctionBegin;
104   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRMPI(ierr);
105   if (rank && *outviewer) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer");
106 
107 #if defined(PETSC_HAVE_MPIIO)
108   if (vbinary->usempiio && *outviewer) {
109     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
110     if (obinary->mfdes != vbinary->mfsub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer");
111     if (obinary->mfsub != MPI_FILE_NULL) {ierr = MPI_File_close(&obinary->mfsub);CHKERRMPI(ierr);}
112     moff = obinary->moff;
113   }
114 #endif
115 
116   if (*outviewer) {
117     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
118     if (obinary->fdes != vbinary->fdes) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer");
119     ierr = PetscFree((*outviewer)->data);CHKERRQ(ierr);
120     ierr = PetscHeaderDestroy(outviewer);CHKERRQ(ierr);
121   }
122 
123 #if defined(PETSC_HAVE_MPIIO)
124   if (vbinary->usempiio) {
125     PetscInt64 ioff = (PetscInt64)moff; /* We could use MPI_OFFSET datatype (requires MPI 2.2) */
126     ierr = MPI_Bcast(&ioff,1,MPIU_INT64,0,PetscObjectComm((PetscObject)viewer));CHKERRMPI(ierr);
127     vbinary->moff = (MPI_Offset)ioff;
128   }
129 #endif
130 
131 #if defined(PETSC_HAVE_MPIIO)
132   ierr = PetscViewerBinarySyncMPIIO(viewer);CHKERRQ(ierr);
133 #endif
134   PetscFunctionReturn(0);
135 }
136 
137 #if defined(PETSC_HAVE_MPIIO)
138 /*@C
139     PetscViewerBinaryGetMPIIOOffset - Gets the current global offset that should be passed to MPI_File_set_view() or MPI_File_{write|read}_at[_all]()
140 
141     Not Collective
142 
143     Input Parameter:
144 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
145 
146     Output Parameter:
147 .   off - the current global offset
148 
149     Level: advanced
150 
151     Fortran Note:
152     This routine is not supported in Fortran.
153 
154     Use PetscViewerBinaryAddMPIIOOffset() to increase this value after you have written a view.
155 
156 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryAddMPIIOOffset()
157 @*/
158 PetscErrorCode PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer,MPI_Offset *off)
159 {
160   PetscViewer_Binary *vbinary;
161 
162   PetscFunctionBegin;
163   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
164   PetscValidPointer(off,2);
165   vbinary = (PetscViewer_Binary*)viewer->data;
166   *off = vbinary->moff;
167   PetscFunctionReturn(0);
168 }
169 
170 /*@C
171     PetscViewerBinaryAddMPIIOOffset - Adds to the current global offset
172 
173     Logically Collective
174 
175     Input Parameters:
176 +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
177 -   off - the addition to the global offset
178 
179     Level: advanced
180 
181     Fortran Note:
182     This routine is not supported in Fortran.
183 
184     Use PetscViewerBinaryGetMPIIOOffset() to get the value that you should pass to MPI_File_set_view() or MPI_File_{write|read}_at[_all]()
185 
186 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
187 @*/
188 PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer,MPI_Offset off)
189 {
190   PetscViewer_Binary *vbinary;
191 
192   PetscFunctionBegin;
193   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
194   PetscValidLogicalCollectiveInt(viewer,(PetscInt)off,2);
195   vbinary = (PetscViewer_Binary*)viewer->data;
196   vbinary->moff += off;
197   PetscFunctionReturn(0);
198 }
199 
200 /*@C
201     PetscViewerBinaryGetMPIIODescriptor - Extracts the MPI IO file descriptor from a PetscViewer.
202 
203     Not Collective
204 
205     Input Parameter:
206 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
207 
208     Output Parameter:
209 .   fdes - file descriptor
210 
211     Level: advanced
212 
213     Fortran Note:
214     This routine is not supported in Fortran.
215 
216 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
217 @*/
218 PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer,MPI_File *fdes)
219 {
220   PetscErrorCode     ierr;
221   PetscViewer_Binary *vbinary;
222 
223   PetscFunctionBegin;
224   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
225   PetscValidPointer(fdes,2);
226   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
227   vbinary = (PetscViewer_Binary*)viewer->data;
228   *fdes = vbinary->mfdes;
229   PetscFunctionReturn(0);
230 }
231 #endif
232 
233 /*@
234     PetscViewerBinarySetUseMPIIO - Sets a binary viewer to use MPI-IO for reading/writing. Must be called
235         before PetscViewerFileSetName()
236 
237     Logically Collective on PetscViewer
238 
239     Input Parameters:
240 +   viewer - the PetscViewer; must be a binary
241 -   use - PETSC_TRUE means MPI-IO will be used
242 
243     Options Database:
244     -viewer_binary_mpiio : Flag for using MPI-IO
245 
246     Level: advanced
247 
248 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
249           PetscViewerBinaryGetUseMPIIO()
250 
251 @*/
252 PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool use)
253 {
254   PetscErrorCode ierr;
255 
256   PetscFunctionBegin;
257   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
258   PetscValidLogicalCollectiveBool(viewer,use,2);
259   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,use));CHKERRQ(ierr);
260   PetscFunctionReturn(0);
261 }
262 
263 #if defined(PETSC_HAVE_MPIIO)
264 static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool use)
265 {
266   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
267   PetscFunctionBegin;
268   if (viewer->setupcalled && vbinary->usempiio != use) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER,"Cannot change MPIIO to %s after setup",PetscBools[use]);
269   vbinary->usempiio = use;
270   PetscFunctionReturn(0);
271 }
272 #endif
273 
274 /*@
275     PetscViewerBinaryGetUseMPIIO - Returns PETSC_TRUE if the binary viewer uses MPI-IO.
276 
277     Not Collective
278 
279     Input Parameter:
280 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
281 
282     Output Parameter:
283 .   use - PETSC_TRUE if MPI-IO is being used
284 
285     Options Database:
286     -viewer_binary_mpiio : Flag for using MPI-IO
287 
288     Level: advanced
289 
290     Note:
291     If MPI-IO is not available, this function will always return PETSC_FALSE
292 
293     Fortran Note:
294     This routine is not supported in Fortran.
295 
296 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
297 @*/
298 PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool *use)
299 {
300   PetscErrorCode ierr;
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
304   PetscValidBoolPointer(use,2);
305   *use = PETSC_FALSE;
306   ierr = PetscTryMethod(viewer,"PetscViewerBinaryGetUseMPIIO_C",(PetscViewer,PetscBool*),(viewer,use));CHKERRQ(ierr);
307   PetscFunctionReturn(0);
308 }
309 
310 #if defined(PETSC_HAVE_MPIIO)
311 static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer,PetscBool  *use)
312 {
313   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
314 
315   PetscFunctionBegin;
316   *use = vbinary->usempiio;
317   PetscFunctionReturn(0);
318 }
319 #endif
320 
321 /*@
322     PetscViewerBinarySetFlowControl - Sets how many messages are allowed to outstanding at the same time during parallel IO reads/writes
323 
324     Not Collective
325 
326     Input Parameters:
327 +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
328 -   fc - the number of messages, defaults to 256 if this function was not called
329 
330     Level: advanced
331 
332 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetFlowControl()
333 
334 @*/
335 PetscErrorCode  PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc)
336 {
337   PetscErrorCode ierr;
338 
339   PetscFunctionBegin;
340   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
341   PetscValidLogicalCollectiveInt(viewer,fc,2);
342   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetFlowControl_C",(PetscViewer,PetscInt),(viewer,fc));CHKERRQ(ierr);
343   PetscFunctionReturn(0);
344 }
345 
346 static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc)
347 {
348   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
349 
350   PetscFunctionBegin;
351   if (fc <= 1) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_OUTOFRANGE,"Flow control count must be greater than 1, %D was set",fc);
352   vbinary->flowcontrol = fc;
353   PetscFunctionReturn(0);
354 }
355 
356 /*@
357     PetscViewerBinaryGetFlowControl - Returns how many messages are allowed to outstanding at the same time during parallel IO reads/writes
358 
359     Not Collective
360 
361     Input Parameter:
362 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
363 
364     Output Parameter:
365 .   fc - the number of messages
366 
367     Level: advanced
368 
369 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinarySetFlowControl()
370 
371 @*/
372 PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt *fc)
373 {
374   PetscErrorCode ierr;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
378   PetscValidIntPointer(fc,2);
379   ierr = PetscUseMethod(viewer,"PetscViewerBinaryGetFlowControl_C",(PetscViewer,PetscInt*),(viewer,fc));CHKERRQ(ierr);
380   PetscFunctionReturn(0);
381 }
382 
383 static PetscErrorCode  PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt *fc)
384 {
385   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
386 
387   PetscFunctionBegin;
388   *fc = vbinary->flowcontrol;
389   PetscFunctionReturn(0);
390 }
391 
392 /*@C
393     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.
394 
395     Collective On PetscViewer
396 
397     Input Parameter:
398 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
399 
400     Output Parameter:
401 .   fdes - file descriptor
402 
403     Level: advanced
404 
405     Notes:
406       For writable binary PetscViewers, the descriptor will only be valid for the
407     first processor in the communicator that shares the PetscViewer. For readable
408     files it will only be valid on nodes that have the file. If node 0 does not
409     have the file it generates an error even if another node does have the file.
410 
411     Fortran Note:
412     This routine is not supported in Fortran.
413 
414     Developer Notes:
415     This must be called on all processes because Dave May changed
416     the source code that this may be trigger a PetscViewerSetUp() call if it was not previously triggered.
417 
418 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
419 @*/
420 PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
421 {
422   PetscErrorCode     ierr;
423   PetscViewer_Binary *vbinary;
424 
425   PetscFunctionBegin;
426   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
427   PetscValidPointer(fdes,2);
428   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
429   vbinary = (PetscViewer_Binary*)viewer->data;
430   *fdes = vbinary->fdes;
431   PetscFunctionReturn(0);
432 }
433 
434 /*@
435     PetscViewerBinarySkipInfo - Binary file will not have .info file created with it
436 
437     Not Collective
438 
439     Input Parameter:
440 .   viewer - PetscViewer context, obtained from PetscViewerCreate()
441 
442     Options Database Key:
443 .   -viewer_binary_skip_info - true indicates do not generate .info file
444 
445     Level: advanced
446 
447     Notes:
448     This must be called after PetscViewerSetType(). If you use PetscViewerBinaryOpen() then
449     you can only skip the info file with the -viewer_binary_skip_info flag. To use the function you must open the
450     viewer with PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinarySkipInfo().
451 
452     The .info contains meta information about the data in the binary file, for example the block size if it was
453     set for a vector or matrix.
454 
455 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
456           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
457 @*/
458 PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
459 {
460   PetscErrorCode ierr;
461 
462   PetscFunctionBegin;
463   ierr = PetscViewerBinarySetSkipInfo(viewer,PETSC_TRUE);CHKERRQ(ierr);
464   PetscFunctionReturn(0);
465 }
466 
467 /*@
468     PetscViewerBinarySetSkipInfo - Binary file will not have .info file created with it
469 
470     Not Collective
471 
472     Input Parameters:
473 +   viewer - PetscViewer context, obtained from PetscViewerCreate()
474 -   skip - PETSC_TRUE implies the .info file will not be generated
475 
476     Options Database Key:
477 .   -viewer_binary_skip_info - true indicates do not generate .info file
478 
479     Level: advanced
480 
481 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
482           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
483 @*/
484 PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer,PetscBool skip)
485 {
486   PetscErrorCode ierr;
487 
488   PetscFunctionBegin;
489   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
490   PetscValidLogicalCollectiveBool(viewer,skip,2);
491   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetSkipInfo_C",(PetscViewer,PetscBool),(viewer,skip));CHKERRQ(ierr);
492   PetscFunctionReturn(0);
493 }
494 
495 static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip)
496 {
497   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
498 
499   PetscFunctionBegin;
500   vbinary->skipinfo = skip;
501   PetscFunctionReturn(0);
502 }
503 
504 /*@
505     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file
506 
507     Not Collective
508 
509     Input Parameter:
510 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
511 
512     Output Parameter:
513 .   skip - PETSC_TRUE implies the .info file was not generated
514 
515     Level: advanced
516 
517     Notes:
518     This must be called after PetscViewerSetType()
519 
520 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
521           PetscViewerBinarySetSkipOptions(), PetscViewerBinarySetSkipInfo()
522 @*/
523 PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip)
524 {
525   PetscErrorCode ierr;
526 
527   PetscFunctionBegin;
528   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
529   PetscValidBoolPointer(skip,2);
530   ierr = PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip));CHKERRQ(ierr);
531   PetscFunctionReturn(0);
532 }
533 
534 static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool *skip)
535 {
536   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
537 
538   PetscFunctionBegin;
539   *skip  = vbinary->skipinfo;
540   PetscFunctionReturn(0);
541 }
542 
543 /*@
544     PetscViewerBinarySetSkipOptions - do not use the PETSc options database when loading objects
545 
546     Not Collective
547 
548     Input Parameters:
549 +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
550 -   skip - PETSC_TRUE means do not use the options from the options database
551 
552     Options Database Key:
553 .   -viewer_binary_skip_options - true means do not use the options from the options database
554 
555     Level: advanced
556 
557     Notes:
558     This must be called after PetscViewerSetType()
559 
560 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
561           PetscViewerBinaryGetSkipOptions()
562 @*/
563 PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscBool skip)
564 {
565   PetscErrorCode ierr;
566 
567   PetscFunctionBegin;
568   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
569   PetscValidLogicalCollectiveBool(viewer,skip,2);
570   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetSkipOptions_C",(PetscViewer,PetscBool),(viewer,skip));CHKERRQ(ierr);
571   PetscFunctionReturn(0);
572 }
573 
574 static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)
575 {
576   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
577 
578   PetscFunctionBegin;
579   vbinary->skipoptions = skip;
580   PetscFunctionReturn(0);
581 }
582 
583 /*@
584     PetscViewerBinaryGetSkipOptions - checks if viewer uses the PETSc options database when loading objects
585 
586     Not Collective
587 
588     Input Parameter:
589 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
590 
591     Output Parameter:
592 .   skip - PETSC_TRUE means do not use
593 
594     Level: advanced
595 
596     Notes:
597     This must be called after PetscViewerSetType()
598 
599 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
600           PetscViewerBinarySetSkipOptions()
601 @*/
602 PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool *skip)
603 {
604   PetscErrorCode ierr;
605 
606   PetscFunctionBegin;
607   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
608   PetscValidBoolPointer(skip,2);
609   ierr = PetscUseMethod(viewer,"PetscViewerBinaryGetSkipOptions_C",(PetscViewer,PetscBool*),(viewer,skip));CHKERRQ(ierr);
610   PetscFunctionReturn(0);
611 }
612 
613 static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer,PetscBool *skip)
614 {
615   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
616 
617   PetscFunctionBegin;
618   *skip = vbinary->skipoptions;
619   PetscFunctionReturn(0);
620 }
621 
622 /*@
623     PetscViewerBinarySetSkipHeader - do not write a header with size information on output, just raw data
624 
625     Not Collective
626 
627     Input Parameters:
628 +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
629 -   skip - PETSC_TRUE means do not write header
630 
631     Options Database Key:
632 .   -viewer_binary_skip_header - PETSC_TRUE means do not write header
633 
634     Level: advanced
635 
636     Notes:
637       This must be called after PetscViewerSetType()
638 
639       Is ignored on anything but a binary viewer
640 
641 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
642           PetscViewerBinaryGetSkipHeader()
643 @*/
644 PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)
645 {
646   PetscErrorCode ierr;
647 
648   PetscFunctionBegin;
649   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
650   PetscValidLogicalCollectiveBool(viewer,skip,2);
651   ierr = PetscTryMethod(viewer,"PetscViewerBinarySetSkipHeader_C",(PetscViewer,PetscBool),(viewer,skip));CHKERRQ(ierr);
652   PetscFunctionReturn(0);
653 }
654 
655 static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip)
656 {
657   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
658 
659   PetscFunctionBegin;
660   vbinary->skipheader = skip;
661   PetscFunctionReturn(0);
662 }
663 
664 /*@
665     PetscViewerBinaryGetSkipHeader - checks whether to write a header with size information on output, or just raw data
666 
667     Not Collective
668 
669     Input Parameter:
670 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
671 
672     Output Parameter:
673 .   skip - PETSC_TRUE means do not write header
674 
675     Level: advanced
676 
677     Notes:
678     This must be called after PetscViewerSetType()
679 
680             Returns false for PETSCSOCKETVIEWER, you cannot skip the header for it.
681 
682 .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
683           PetscViewerBinarySetSkipHeader()
684 @*/
685 PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer,PetscBool  *skip)
686 {
687   PetscErrorCode ierr;
688 
689   PetscFunctionBegin;
690   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
691   PetscValidBoolPointer(skip,2);
692   ierr = PetscUseMethod(viewer,"PetscViewerBinaryGetSkipHeader_C",(PetscViewer,PetscBool*),(viewer,skip));CHKERRQ(ierr);
693   PetscFunctionReturn(0);
694 }
695 
696 static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer,PetscBool  *skip)
697 {
698   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
699 
700   PetscFunctionBegin;
701   *skip = vbinary->skipheader;
702   PetscFunctionReturn(0);
703 }
704 
705 /*@C
706     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
707           info file associated with a binary file.
708 
709     Not Collective
710 
711     Input Parameter:
712 .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
713 
714     Output Parameter:
715 .   file - file pointer  Always returns NULL if not a binary viewer
716 
717     Level: advanced
718 
719     Notes:
720       For writable binary PetscViewers, the descriptor will only be valid for the
721     first processor in the communicator that shares the PetscViewer.
722 
723     Fortran Note:
724     This routine is not supported in Fortran.
725 
726 .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
727 @*/
728 PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
729 {
730   PetscErrorCode ierr;
731 
732   PetscFunctionBegin;
733   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
734   PetscValidPointer(file,2);
735   *file = NULL;
736   ierr = PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file));CHKERRQ(ierr);
737   PetscFunctionReturn(0);
738 }
739 
740 static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE **file)
741 {
742   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
743   PetscErrorCode     ierr;
744 
745   PetscFunctionBegin;
746   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
747   *file = vbinary->fdes_info;
748   if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
749     if (vbinary->fdes_info) {
750       FILE *info = vbinary->fdes_info;
751       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");CHKERRQ(ierr);
752       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#$$ Set.filename = '%s';\n",vbinary->filename);CHKERRQ(ierr);
753       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#$$ fd = PetscOpenFile(Set.filename);\n");CHKERRQ(ierr);
754       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");CHKERRQ(ierr);
755     }
756     vbinary->matlabheaderwritten = PETSC_TRUE;
757   }
758   PetscFunctionReturn(0);
759 }
760 
761 #if defined(PETSC_HAVE_MPIIO)
762 static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
763 {
764   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
765   PetscErrorCode     ierr;
766 
767   PetscFunctionBegin;
768   if (vbinary->mfdes != MPI_FILE_NULL) {
769     ierr = MPI_File_close(&vbinary->mfdes);CHKERRMPI(ierr);
770   }
771   if (vbinary->mfsub != MPI_FILE_NULL) {
772     ierr = MPI_File_close(&vbinary->mfsub);CHKERRMPI(ierr);
773   }
774   vbinary->moff = 0;
775   PetscFunctionReturn(0);
776 }
777 #endif
778 
779 static PetscErrorCode PetscViewerFileClose_BinarySTDIO(PetscViewer v)
780 {
781   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
782   PetscErrorCode     ierr;
783 
784   PetscFunctionBegin;
785   if (vbinary->fdes != -1) {
786     ierr = PetscBinaryClose(vbinary->fdes);CHKERRQ(ierr);
787     vbinary->fdes = -1;
788     if (vbinary->storecompressed) {
789       char cmd[8+PETSC_MAX_PATH_LEN],out[64+PETSC_MAX_PATH_LEN] = "";
790       const char *gzfilename = vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename;
791       /* compress the file */
792       ierr = PetscStrncpy(cmd,"gzip -f ",sizeof(cmd));CHKERRQ(ierr);
793       ierr = PetscStrlcat(cmd,gzfilename,sizeof(cmd));CHKERRQ(ierr);
794 #if defined(PETSC_HAVE_POPEN)
795       {
796         FILE *fp;
797         ierr = PetscPOpen(PETSC_COMM_SELF,NULL,cmd,"r",&fp);CHKERRQ(ierr);
798         if (fgets(out,(int)(sizeof(out)-1),fp)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error from command %s\n%s",cmd,out);
799         ierr = PetscPClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr);
800       }
801 #endif
802     }
803   }
804   ierr = PetscFree(vbinary->ogzfilename);CHKERRQ(ierr);
805   PetscFunctionReturn(0);
806 }
807 
808 static PetscErrorCode PetscViewerFileClose_BinaryInfo(PetscViewer v)
809 {
810   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
811   PetscErrorCode     ierr;
812 
813   PetscFunctionBegin;
814   if (v->format == PETSC_VIEWER_BINARY_MATLAB && vbinary->matlabheaderwritten) {
815     if (vbinary->fdes_info) {
816       FILE *info = vbinary->fdes_info;
817       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");CHKERRQ(ierr);
818       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#$$ close(fd);\n");CHKERRQ(ierr);
819       ierr = PetscFPrintf(PETSC_COMM_SELF,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");CHKERRQ(ierr);
820     }
821   }
822   if (vbinary->fdes_info) {
823     FILE *info = vbinary->fdes_info;
824     vbinary->fdes_info = NULL;
825     if (fclose(info)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
826   }
827   PetscFunctionReturn(0);
828 }
829 
830 static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
831 {
832   PetscErrorCode     ierr;
833 
834   PetscFunctionBegin;
835 #if defined(PETSC_HAVE_MPIIO)
836   ierr = PetscViewerFileClose_BinaryMPIIO(v);CHKERRQ(ierr);
837 #endif
838   ierr = PetscViewerFileClose_BinarySTDIO(v);CHKERRQ(ierr);
839   ierr = PetscViewerFileClose_BinaryInfo(v);CHKERRQ(ierr);
840   PetscFunctionReturn(0);
841 }
842 
843 static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
844 {
845   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
846   PetscErrorCode     ierr;
847 
848   PetscFunctionBegin;
849   ierr = PetscViewerFileClose_Binary(v);CHKERRQ(ierr);
850   ierr = PetscFree(vbinary->filename);CHKERRQ(ierr);
851   ierr = PetscFree(vbinary);CHKERRQ(ierr);
852 
853   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",NULL);CHKERRQ(ierr);
854   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",NULL);CHKERRQ(ierr);
855   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",NULL);CHKERRQ(ierr);
856   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",NULL);CHKERRQ(ierr);
857   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",NULL);CHKERRQ(ierr);
858   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",NULL);CHKERRQ(ierr);
859   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",NULL);CHKERRQ(ierr);
860   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",NULL);CHKERRQ(ierr);
861   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",NULL);CHKERRQ(ierr);
862   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",NULL);CHKERRQ(ierr);
863   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",NULL);CHKERRQ(ierr);
864   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",NULL);CHKERRQ(ierr);
865   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",NULL);CHKERRQ(ierr);
866 #if defined(PETSC_HAVE_MPIIO)
867   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",NULL);CHKERRQ(ierr);
868   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",NULL);CHKERRQ(ierr);
869 #endif
870   PetscFunctionReturn(0);
871 }
872 
873 /*@C
874    PetscViewerBinaryOpen - Opens a file for binary input/output.
875 
876    Collective
877 
878    Input Parameters:
879 +  comm - MPI communicator
880 .  name - name of file
881 -  mode - open mode of file
882 $    FILE_MODE_WRITE - create new file for binary output
883 $    FILE_MODE_READ - open existing file for binary input
884 $    FILE_MODE_APPEND - open existing file for binary output
885 
886    Output Parameter:
887 .  viewer - PetscViewer for binary input/output to use with the specified file
888 
889     Options Database Keys:
890 +    -viewer_binary_filename <name> -
891 .    -viewer_binary_skip_info -
892 .    -viewer_binary_skip_options -
893 .    -viewer_binary_skip_header -
894 -    -viewer_binary_mpiio -
895 
896    Level: beginner
897 
898    Note:
899    This PetscViewer should be destroyed with PetscViewerDestroy().
900 
901     For reading files, the filename may begin with ftp:// or http:// and/or
902     end with .gz; in this case file is brought over and uncompressed.
903 
904     For creating files, if the file name ends with .gz it is automatically
905     compressed when closed.
906 
907 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
908           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
909           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead(), PetscViewerBinarySetUseMPIIO(),
910           PetscViewerBinaryGetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
911 @*/
912 PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode mode,PetscViewer *viewer)
913 {
914   PetscErrorCode ierr;
915 
916   PetscFunctionBegin;
917   ierr = PetscViewerCreate(comm,viewer);CHKERRQ(ierr);
918   ierr = PetscViewerSetType(*viewer,PETSCVIEWERBINARY);CHKERRQ(ierr);
919   ierr = PetscViewerFileSetMode(*viewer,mode);CHKERRQ(ierr);
920   ierr = PetscViewerFileSetName(*viewer,name);CHKERRQ(ierr);
921   ierr = PetscViewerSetFromOptions(*viewer);CHKERRQ(ierr);
922   PetscFunctionReturn(0);
923 }
924 
925 #if defined(PETSC_HAVE_MPIIO)
926 static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype,PetscBool write)
927 {
928   MPI_Comm           comm = PetscObjectComm((PetscObject)viewer);
929   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
930   MPI_File           mfdes = vbinary->mfdes;
931   PetscErrorCode     ierr;
932   MPI_Datatype       mdtype;
933   PetscMPIInt        rank,cnt;
934   MPI_Status         status;
935   MPI_Aint           ul,dsize;
936 
937   PetscFunctionBegin;
938   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
939   ierr = PetscMPIIntCast(num,&cnt);CHKERRQ(ierr);
940   ierr = PetscDataTypeToMPIDataType(dtype,&mdtype);CHKERRQ(ierr);
941   if (write) {
942     if (rank == 0) {
943       ierr = MPIU_File_write_at(mfdes,vbinary->moff,data,cnt,mdtype,&status);CHKERRQ(ierr);
944     }
945   } else {
946     if (rank == 0) {
947       ierr = MPIU_File_read_at(mfdes,vbinary->moff,data,cnt,mdtype,&status);CHKERRQ(ierr);
948       if (cnt > 0) {ierr = MPI_Get_count(&status,mdtype,&cnt);CHKERRMPI(ierr);}
949     }
950     ierr = MPI_Bcast(&cnt,1,MPI_INT,0,comm);CHKERRMPI(ierr);
951     ierr = MPI_Bcast(data,cnt,mdtype,0,comm);CHKERRMPI(ierr);
952   }
953   ierr = MPI_Type_get_extent(mdtype,&ul,&dsize);CHKERRMPI(ierr);
954   vbinary->moff += dsize*cnt;
955   if (count) *count = cnt;
956   PetscFunctionReturn(0);
957 }
958 #endif
959 
960 /*@C
961    PetscViewerBinaryRead - Reads from a binary file, all processors get the same result
962 
963    Collective
964 
965    Input Parameters:
966 +  viewer - the binary viewer
967 .  data - location of the data to be written
968 .  num - number of items of data to read
969 -  dtype - type of data to read
970 
971    Output Parameters:
972 .  count - number of items of data actually read, or NULL.
973 
974    Level: beginner
975 
976 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
977           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
978           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
979 @*/
980 PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype)
981 {
982   PetscErrorCode     ierr;
983   PetscViewer_Binary *vbinary;
984 
985   PetscFunctionBegin;
986   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
987   PetscValidLogicalCollectiveInt(viewer,num,3);
988   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
989   vbinary = (PetscViewer_Binary*)viewer->data;
990 #if defined(PETSC_HAVE_MPIIO)
991   if (vbinary->usempiio) {
992     ierr = PetscViewerBinaryWriteReadMPIIO(viewer,data,num,count,dtype,PETSC_FALSE);CHKERRQ(ierr);
993   } else {
994 #endif
995     ierr = PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,num,count,dtype);CHKERRQ(ierr);
996 #if defined(PETSC_HAVE_MPIIO)
997   }
998 #endif
999   PetscFunctionReturn(0);
1000 }
1001 
1002 /*@C
1003    PetscViewerBinaryWrite - writes to a binary file, only from the first process
1004 
1005    Collective
1006 
1007    Input Parameters:
1008 +  viewer - the binary viewer
1009 .  data - location of data
1010 .  count - number of items of data to write
1011 -  dtype - type of data to write
1012 
1013    Level: beginner
1014 
1015 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
1016           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(), PetscDataType
1017           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
1018 @*/
1019 PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer,const void *data,PetscInt count,PetscDataType dtype)
1020 {
1021   PetscErrorCode     ierr;
1022   PetscViewer_Binary *vbinary;
1023 
1024   PetscFunctionBegin;
1025   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
1026   PetscValidLogicalCollectiveInt(viewer,count,3);
1027   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1028   vbinary = (PetscViewer_Binary*)viewer->data;
1029 #if defined(PETSC_HAVE_MPIIO)
1030   if (vbinary->usempiio) {
1031     ierr = PetscViewerBinaryWriteReadMPIIO(viewer,(void*)data,count,NULL,dtype,PETSC_TRUE);CHKERRQ(ierr);
1032   } else {
1033 #endif
1034     ierr = PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype);CHKERRQ(ierr);
1035 #if defined(PETSC_HAVE_MPIIO)
1036   }
1037 #endif
1038   PetscFunctionReturn(0);
1039 }
1040 
1041 static PetscErrorCode PetscViewerBinaryWriteReadAll(PetscViewer viewer,PetscBool write,void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)
1042 {
1043   MPI_Comm              comm = PetscObjectComm((PetscObject)viewer);
1044   PetscMPIInt           size,rank;
1045   MPI_Datatype          mdtype;
1046   PETSC_UNUSED MPI_Aint lb;
1047   MPI_Aint              dsize;
1048   PetscBool             useMPIIO;
1049   PetscErrorCode        ierr;
1050 
1051   PetscFunctionBegin;
1052   PetscValidHeaderSpecificType(viewer,PETSC_VIEWER_CLASSID,1,PETSCVIEWERBINARY);
1053   PetscValidLogicalCollectiveBool(viewer,((start>=0)||(start==PETSC_DETERMINE)),5);
1054   PetscValidLogicalCollectiveBool(viewer,((total>=0)||(total==PETSC_DETERMINE)),6);
1055   PetscValidLogicalCollectiveInt(viewer,total,6);
1056   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1057 
1058   ierr = PetscDataTypeToMPIDataType(dtype,&mdtype);CHKERRQ(ierr);
1059   ierr = MPI_Type_get_extent(mdtype,&lb,&dsize);CHKERRMPI(ierr);
1060   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
1061   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
1062 
1063   ierr = PetscViewerBinaryGetUseMPIIO(viewer,&useMPIIO);CHKERRQ(ierr);
1064 #if defined(PETSC_HAVE_MPIIO)
1065   if (useMPIIO) {
1066     MPI_File       mfdes;
1067     MPI_Offset     off;
1068     PetscMPIInt    cnt;
1069 
1070     if (start == PETSC_DETERMINE) {
1071       ierr = MPI_Scan(&count,&start,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr);
1072       start -= count;
1073     }
1074     if (total == PETSC_DETERMINE) {
1075       total = start + count;
1076       ierr = MPI_Bcast(&total,1,MPIU_INT,size-1,comm);CHKERRMPI(ierr);
1077     }
1078     ierr = PetscMPIIntCast(count,&cnt);CHKERRQ(ierr);
1079     ierr = PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);CHKERRQ(ierr);
1080     ierr = PetscViewerBinaryGetMPIIOOffset(viewer,&off);CHKERRQ(ierr);
1081     off += (MPI_Offset)(start*dsize);
1082     if (write) {
1083       ierr = MPIU_File_write_at_all(mfdes,off,data,cnt,mdtype,MPI_STATUS_IGNORE);CHKERRQ(ierr);
1084     } else {
1085       ierr = MPIU_File_read_at_all(mfdes,off,data,cnt,mdtype,MPI_STATUS_IGNORE);CHKERRQ(ierr);
1086     }
1087     off  = (MPI_Offset)(total*dsize);
1088     ierr = PetscViewerBinaryAddMPIIOOffset(viewer,off);CHKERRQ(ierr);
1089     PetscFunctionReturn(0);
1090   }
1091 #endif
1092   {
1093     int         fdes;
1094     char        *workbuf = NULL;
1095     PetscInt    tcount = rank == 0 ? 0 : count,maxcount=0,message_count,flowcontrolcount;
1096     PetscMPIInt tag,cnt,maxcnt,scnt=0,rcnt=0,j;
1097     MPI_Status  status;
1098 
1099     ierr = PetscCommGetNewTag(comm,&tag);CHKERRQ(ierr);
1100     ierr = MPI_Reduce(&tcount,&maxcount,1,MPIU_INT,MPI_MAX,0,comm);CHKERRMPI(ierr);
1101     ierr = PetscMPIIntCast(maxcount,&maxcnt);CHKERRQ(ierr);
1102     ierr = PetscMPIIntCast(count,&cnt);CHKERRQ(ierr);
1103 
1104     ierr = PetscViewerBinaryGetDescriptor(viewer,&fdes);CHKERRQ(ierr);
1105     ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr);
1106     if (rank == 0) {
1107       ierr = PetscMalloc(maxcnt*dsize,&workbuf);CHKERRQ(ierr);
1108       if (write) {
1109         ierr = PetscBinaryWrite(fdes,data,cnt,dtype);CHKERRQ(ierr);
1110       } else {
1111         ierr = PetscBinaryRead(fdes,data,cnt,NULL,dtype);CHKERRQ(ierr);
1112       }
1113       for (j=1; j<size; j++) {
1114         ierr = PetscViewerFlowControlStepMain(viewer,j,&message_count,flowcontrolcount);CHKERRQ(ierr);
1115         if (write) {
1116           ierr = MPI_Recv(workbuf,maxcnt,mdtype,j,tag,comm,&status);CHKERRMPI(ierr);
1117           ierr = MPI_Get_count(&status,mdtype,&rcnt);CHKERRMPI(ierr);
1118           ierr = PetscBinaryWrite(fdes,workbuf,rcnt,dtype);CHKERRQ(ierr);
1119         } else {
1120           ierr = MPI_Recv(&scnt,1,MPI_INT,j,tag,comm,MPI_STATUS_IGNORE);CHKERRMPI(ierr);
1121           ierr = PetscBinaryRead(fdes,workbuf,scnt,NULL,dtype);CHKERRQ(ierr);
1122           ierr = MPI_Send(workbuf,scnt,mdtype,j,tag,comm);CHKERRMPI(ierr);
1123         }
1124       }
1125       ierr = PetscFree(workbuf);CHKERRQ(ierr);
1126       ierr = PetscViewerFlowControlEndMain(viewer,&message_count);CHKERRQ(ierr);
1127     } else {
1128       ierr = PetscViewerFlowControlStepWorker(viewer,rank,&message_count);CHKERRQ(ierr);
1129       if (write) {
1130         ierr = MPI_Send(data,cnt,mdtype,0,tag,comm);CHKERRMPI(ierr);
1131       } else {
1132         ierr = MPI_Send(&cnt,1,MPI_INT,0,tag,comm);CHKERRMPI(ierr);
1133         ierr = MPI_Recv(data,cnt,mdtype,0,tag,comm,MPI_STATUS_IGNORE);CHKERRMPI(ierr);
1134       }
1135       ierr = PetscViewerFlowControlEndWorker(viewer,&message_count);CHKERRQ(ierr);
1136     }
1137   }
1138   PetscFunctionReturn(0);
1139 }
1140 
1141 /*@C
1142    PetscViewerBinaryReadAll - reads from a binary file from all processes
1143 
1144    Collective
1145 
1146    Input Parameters:
1147 +  viewer - the binary viewer
1148 .  data - location of data
1149 .  count - local number of items of data to read
1150 .  start - local start, can be PETSC_DETERMINE
1151 .  total - global number of items of data to read, can be PETSC_DETERMINE
1152 -  dtype - type of data to read
1153 
1154    Level: advanced
1155 
1156 .seealso: PetscViewerBinaryOpen(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryRead(), PetscViewerBinaryWriteAll()
1157 @*/
1158 PetscErrorCode PetscViewerBinaryReadAll(PetscViewer viewer,void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)
1159 {
1160   PetscErrorCode ierr;
1161   PetscFunctionBegin;
1162   ierr = PetscViewerBinaryWriteReadAll(viewer,PETSC_FALSE,data,count,start,total,dtype);CHKERRQ(ierr);
1163   PetscFunctionReturn(0);
1164 }
1165 
1166 /*@C
1167    PetscViewerBinaryWriteAll - writes to a binary file from all processes
1168 
1169    Collective
1170 
1171    Input Parameters:
1172 +  viewer - the binary viewer
1173 .  data - location of data
1174 .  count - local number of items of data to write
1175 .  start - local start, can be PETSC_DETERMINE
1176 .  total - global number of items of data to write, can be PETSC_DETERMINE
1177 -  dtype - type of data to write
1178 
1179    Level: advanced
1180 
1181 .seealso: PetscViewerBinaryOpen(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryWriteAll(), PetscViewerBinaryReadAll()
1182 @*/
1183 PetscErrorCode PetscViewerBinaryWriteAll(PetscViewer viewer,const void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)
1184 {
1185   PetscErrorCode ierr;
1186   PetscFunctionBegin;
1187   ierr = PetscViewerBinaryWriteReadAll(viewer,PETSC_TRUE,(void*)data,count,start,total,dtype);CHKERRQ(ierr);
1188   PetscFunctionReturn(0);
1189 }
1190 
1191 /*@C
1192    PetscViewerBinaryWriteStringArray - writes to a binary file, only from the first process an array of strings
1193 
1194    Collective
1195 
1196    Input Parameters:
1197 +  viewer - the binary viewer
1198 -  data - location of the array of strings
1199 
1200    Level: intermediate
1201 
1202     Notes:
1203     array of strings is null terminated
1204 
1205 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
1206           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
1207           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
1208 @*/
1209 PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer,const char * const *data)
1210 {
1211   PetscErrorCode ierr;
1212   PetscInt       i,n = 0,*sizes;
1213   size_t         len;
1214 
1215   PetscFunctionBegin;
1216   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1217   /* count number of strings */
1218   while (data[n++]);
1219   n--;
1220   ierr = PetscMalloc1(n+1,&sizes);CHKERRQ(ierr);
1221   sizes[0] = n;
1222   for (i=0; i<n; i++) {
1223     ierr = PetscStrlen(data[i],&len);CHKERRQ(ierr);
1224     sizes[i+1] = (PetscInt)len + 1; /* size includes space for the null terminator */
1225   }
1226   ierr = PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT);CHKERRQ(ierr);
1227   for (i=0; i<n; i++) {
1228     ierr = PetscViewerBinaryWrite(viewer,(void*)data[i],sizes[i+1],PETSC_CHAR);CHKERRQ(ierr);
1229   }
1230   ierr = PetscFree(sizes);CHKERRQ(ierr);
1231   PetscFunctionReturn(0);
1232 }
1233 
1234 /*@C
1235    PetscViewerBinaryReadStringArray - reads a binary file an array of strings
1236 
1237    Collective
1238 
1239    Input Parameter:
1240 .  viewer - the binary viewer
1241 
1242    Output Parameter:
1243 .  data - location of the array of strings
1244 
1245    Level: intermediate
1246 
1247     Notes:
1248     array of strings is null terminated
1249 
1250 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
1251           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
1252           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
1253 @*/
1254 PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
1255 {
1256   PetscErrorCode ierr;
1257   PetscInt       i,n,*sizes,N = 0;
1258 
1259   PetscFunctionBegin;
1260   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1261   /* count number of strings */
1262   ierr = PetscViewerBinaryRead(viewer,&n,1,NULL,PETSC_INT);CHKERRQ(ierr);
1263   ierr = PetscMalloc1(n,&sizes);CHKERRQ(ierr);
1264   ierr = PetscViewerBinaryRead(viewer,sizes,n,NULL,PETSC_INT);CHKERRQ(ierr);
1265   for (i=0; i<n; i++) N += sizes[i];
1266   ierr = PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);CHKERRQ(ierr);
1267   (*data)[0] = (char*)((*data) + n + 1);
1268   for (i=1; i<n; i++) (*data)[i] = (*data)[i-1] + sizes[i-1];
1269   ierr = PetscViewerBinaryRead(viewer,(*data)[0],N,NULL,PETSC_CHAR);CHKERRQ(ierr);
1270   (*data)[n] = NULL;
1271   ierr = PetscFree(sizes);CHKERRQ(ierr);
1272   PetscFunctionReturn(0);
1273 }
1274 
1275 /*@C
1276      PetscViewerFileSetMode - Sets the open mode of file
1277 
1278     Logically Collective on PetscViewer
1279 
1280   Input Parameters:
1281 +  viewer - the PetscViewer; must be a a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
1282 -  mode - open mode of file
1283 $    FILE_MODE_WRITE - create new file for output
1284 $    FILE_MODE_READ - open existing file for input
1285 $    FILE_MODE_APPEND - open existing file for output
1286 
1287   Level: advanced
1288 
1289 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
1290 
1291 @*/
1292 PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode mode)
1293 {
1294   PetscErrorCode ierr;
1295 
1296   PetscFunctionBegin;
1297   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1298   PetscValidLogicalCollectiveEnum(viewer,mode,2);
1299   if (mode == FILE_MODE_UNDEFINED) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Cannot set FILE_MODE_UNDEFINED");
1300   else if (mode < FILE_MODE_UNDEFINED || mode > FILE_MODE_APPEND_UPDATE) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_OUTOFRANGE,"Invalid file mode %d",(int)mode);
1301   ierr = PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,mode));CHKERRQ(ierr);
1302   PetscFunctionReturn(0);
1303 }
1304 
1305 static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode mode)
1306 {
1307   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1308 
1309   PetscFunctionBegin;
1310   if (viewer->setupcalled && vbinary->filemode != mode) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER,"Cannot change mode to %s after setup",PetscFileModes[mode]);
1311   vbinary->filemode = mode;
1312   PetscFunctionReturn(0);
1313 }
1314 
1315 /*@C
1316      PetscViewerFileGetMode - Gets the open mode of file
1317 
1318     Not Collective
1319 
1320   Input Parameter:
1321 .  viewer - the PetscViewer; must be a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
1322 
1323   Output Parameter:
1324 .  mode - open mode of file
1325 $    FILE_MODE_WRITE - create new file for binary output
1326 $    FILE_MODE_READ - open existing file for binary input
1327 $    FILE_MODE_APPEND - open existing file for binary output
1328 
1329   Level: advanced
1330 
1331 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
1332 
1333 @*/
1334 PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *mode)
1335 {
1336   PetscErrorCode ierr;
1337 
1338   PetscFunctionBegin;
1339   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1340   PetscValidPointer(mode,2);
1341   ierr = PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,mode));CHKERRQ(ierr);
1342   PetscFunctionReturn(0);
1343 }
1344 
1345 static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *mode)
1346 {
1347   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1348 
1349   PetscFunctionBegin;
1350   *mode = vbinary->filemode;
1351   PetscFunctionReturn(0);
1352 }
1353 
1354 static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
1355 {
1356   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1357   PetscErrorCode     ierr;
1358 
1359   PetscFunctionBegin;
1360   if (viewer->setupcalled && vbinary->filename) {
1361     /* gzip can be run after the file with the previous filename has been closed */
1362     ierr = PetscFree(vbinary->ogzfilename);CHKERRQ(ierr);
1363     ierr = PetscStrallocpy(vbinary->filename,&vbinary->ogzfilename);CHKERRQ(ierr);
1364   }
1365   ierr = PetscFree(vbinary->filename);CHKERRQ(ierr);
1366   ierr = PetscStrallocpy(name,&vbinary->filename);CHKERRQ(ierr);
1367   viewer->setupcalled = PETSC_FALSE;
1368   PetscFunctionReturn(0);
1369 }
1370 
1371 static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
1372 {
1373   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1374 
1375   PetscFunctionBegin;
1376   *name = vbinary->filename;
1377   PetscFunctionReturn(0);
1378 }
1379 
1380 #if defined(PETSC_HAVE_MPIIO)
1381 static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1382 {
1383   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1384   int                amode;
1385   PetscErrorCode     ierr;
1386 
1387   PetscFunctionBegin;
1388   vbinary->storecompressed = PETSC_FALSE;
1389 
1390   vbinary->moff = 0;
1391   switch (vbinary->filemode) {
1392   case FILE_MODE_READ:   amode = MPI_MODE_RDONLY; break;
1393   case FILE_MODE_WRITE:  amode = MPI_MODE_WRONLY | MPI_MODE_CREATE; break;
1394   case FILE_MODE_APPEND: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_APPEND; break;
1395   case FILE_MODE_UNDEFINED: SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerSetUp()");
1396   default: SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[vbinary->filemode]);
1397   }
1398   ierr = MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfdes);CHKERRMPI(ierr);
1399   /*
1400       The MPI standard does not have MPI_MODE_TRUNCATE. We emulate this behavior by setting the file size to zero.
1401   */
1402   if (vbinary->filemode == FILE_MODE_WRITE) {ierr = MPI_File_set_size(vbinary->mfdes,0);CHKERRMPI(ierr);}
1403   /*
1404       Initially, all processes view the file as a linear byte stream. Therefore, for files opened with MPI_MODE_APPEND,
1405       MPI_File_get_position[_shared](fh, &offset) returns the absolute byte position at the end of file.
1406       Otherwise, we would need to call MPI_File_get_byte_offset(fh, offset, &byte_offset) to convert
1407       the offset in etype units to an absolute byte position.
1408    */
1409   if (vbinary->filemode == FILE_MODE_APPEND) {ierr = MPI_File_get_position(vbinary->mfdes,&vbinary->moff);CHKERRMPI(ierr);}
1410   PetscFunctionReturn(0);
1411 }
1412 #endif
1413 
1414 static PetscErrorCode PetscViewerFileSetUp_BinarySTDIO(PetscViewer viewer)
1415 {
1416   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1417   const char         *fname;
1418   char               bname[PETSC_MAX_PATH_LEN],*gz;
1419   PetscBool          found;
1420   PetscMPIInt        rank;
1421   PetscErrorCode     ierr;
1422 
1423   PetscFunctionBegin;
1424   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRMPI(ierr);
1425 
1426   /* if file name ends in .gz strip that off and note user wants file compressed */
1427   vbinary->storecompressed = PETSC_FALSE;
1428   if (vbinary->filemode == FILE_MODE_WRITE) {
1429     ierr = PetscStrstr(vbinary->filename,".gz",&gz);CHKERRQ(ierr);
1430     if (gz && gz[3] == 0) {*gz = 0; vbinary->storecompressed = PETSC_TRUE;}
1431   }
1432 #if !defined(PETSC_HAVE_POPEN)
1433   if (vbinary->storecompressed) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP_SYS,"Cannot run gzip on this machine");
1434 #endif
1435 
1436   fname = vbinary->filename;
1437   if (vbinary->filemode == FILE_MODE_READ) { /* possibly get the file from remote site or compressed file */
1438     ierr  = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),fname,bname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1439     if (!found) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_OPEN,"Cannot locate file: %s",fname);
1440     fname = bname;
1441   }
1442 
1443   vbinary->fdes = -1;
1444   if (rank == 0) { /* only first processor opens file*/
1445     PetscFileMode mode = vbinary->filemode;
1446     if (mode == FILE_MODE_APPEND) {
1447       /* check if asked to append to a non-existing file */
1448       ierr = PetscTestFile(fname,'\0',&found);CHKERRQ(ierr);
1449       if (!found) mode = FILE_MODE_WRITE;
1450     }
1451     ierr = PetscBinaryOpen(fname,mode,&vbinary->fdes);CHKERRQ(ierr);
1452   }
1453   PetscFunctionReturn(0);
1454 }
1455 
1456 static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
1457 {
1458   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1459   PetscMPIInt        rank;
1460   PetscBool          found;
1461   PetscErrorCode     ierr;
1462 
1463   PetscFunctionBegin;
1464   vbinary->fdes_info = NULL;
1465   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRMPI(ierr);
1466   if (!vbinary->skipinfo && (vbinary->filemode == FILE_MODE_READ || rank == 0)) {
1467     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN],*gz;
1468 
1469     ierr = PetscStrncpy(infoname,vbinary->filename,sizeof(infoname));CHKERRQ(ierr);
1470     /* remove .gz if it ends file name */
1471     ierr = PetscStrstr(infoname,".gz",&gz);CHKERRQ(ierr);
1472     if (gz && gz[3] == 0) *gz = 0;
1473 
1474     ierr = PetscStrlcat(infoname,".info",sizeof(infoname));CHKERRQ(ierr);
1475     if (vbinary->filemode == FILE_MODE_READ) {
1476       ierr = PetscFixFilename(infoname,iname);CHKERRQ(ierr);
1477       ierr = PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr);
1478       if (found) {ierr = PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);CHKERRQ(ierr);}
1479     } else if (rank == 0) { /* write or append */
1480       const char *omode = (vbinary->filemode == FILE_MODE_APPEND) ? "a" : "w";
1481       vbinary->fdes_info = fopen(infoname,omode);
1482       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1483     }
1484   }
1485   PetscFunctionReturn(0);
1486 }
1487 
1488 static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
1489 {
1490   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1491   PetscBool          usempiio;
1492   PetscErrorCode     ierr;
1493 
1494   PetscFunctionBegin;
1495   if (!vbinary->setfromoptionscalled) {ierr = PetscViewerSetFromOptions(viewer);CHKERRQ(ierr);}
1496   if (!vbinary->filename) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetName()");
1497   if (vbinary->filemode == (PetscFileMode)-1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode()");
1498   ierr = PetscViewerFileClose_Binary(viewer);CHKERRQ(ierr);
1499 
1500   ierr = PetscViewerBinaryGetUseMPIIO(viewer,&usempiio);CHKERRQ(ierr);
1501   if (usempiio) {
1502 #if defined(PETSC_HAVE_MPIIO)
1503     ierr = PetscViewerFileSetUp_BinaryMPIIO(viewer);CHKERRQ(ierr);
1504 #endif
1505   } else {
1506     ierr = PetscViewerFileSetUp_BinarySTDIO(viewer);CHKERRQ(ierr);
1507   }
1508   ierr = PetscViewerFileSetUp_BinaryInfo(viewer);CHKERRQ(ierr);
1509 
1510   ierr = PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);CHKERRQ(ierr);
1511   PetscFunctionReturn(0);
1512 }
1513 
1514 static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
1515 {
1516   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
1517   const char         *fname = vbinary->filename ? vbinary->filename : "not yet set";
1518   const char         *fmode = vbinary->filemode != (PetscFileMode) -1 ? PetscFileModes[vbinary->filemode] : "not yet set";
1519   PetscBool          usempiio;
1520   PetscErrorCode     ierr;
1521 
1522   PetscFunctionBegin;
1523   ierr = PetscViewerBinaryGetUseMPIIO(v,&usempiio);CHKERRQ(ierr);
1524   ierr = PetscViewerASCIIPrintf(viewer,"Filename: %s\n",fname);CHKERRQ(ierr);
1525   ierr = PetscViewerASCIIPrintf(viewer,"Mode: %s (%s)\n",fmode,usempiio ? "mpiio" : "stdio");CHKERRQ(ierr);
1526   PetscFunctionReturn(0);
1527 }
1528 
1529 static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer viewer)
1530 {
1531   PetscViewer_Binary *binary = (PetscViewer_Binary*)viewer->data;
1532   char               defaultname[PETSC_MAX_PATH_LEN];
1533   PetscBool          flg;
1534   PetscErrorCode     ierr;
1535 
1536   PetscFunctionBegin;
1537   if (viewer->setupcalled) PetscFunctionReturn(0);
1538   ierr = PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");CHKERRQ(ierr);
1539   ierr = PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");CHKERRQ(ierr);
1540   ierr = PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,sizeof(defaultname),&flg);CHKERRQ(ierr);
1541   if (flg) { ierr = PetscViewerFileSetName_Binary(viewer,defaultname);CHKERRQ(ierr); }
1542   ierr = PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",binary->skipinfo,&binary->skipinfo,NULL);CHKERRQ(ierr);
1543   ierr = PetscOptionsBool("-viewer_binary_skip_options","Skip parsing Vec/Mat load options","PetscViewerBinarySetSkipOptions",binary->skipoptions,&binary->skipoptions,NULL);CHKERRQ(ierr);
1544   ierr = PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",binary->skipheader,&binary->skipheader,NULL);CHKERRQ(ierr);
1545 #if defined(PETSC_HAVE_MPIIO)
1546   ierr = PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",binary->usempiio,&binary->usempiio,NULL);CHKERRQ(ierr);
1547 #else
1548   ierr = PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file (NOT AVAILABLE)","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL);CHKERRQ(ierr);
1549 #endif
1550   ierr = PetscOptionsTail();CHKERRQ(ierr);
1551   binary->setfromoptionscalled = PETSC_TRUE;
1552   PetscFunctionReturn(0);
1553 }
1554 
1555 /*MC
1556    PETSCVIEWERBINARY - A viewer that saves to binary files
1557 
1558 .seealso:  PetscViewerBinaryOpen(), PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD, PetscViewerCreate(), PetscViewerASCIIOpen(),
1559            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, PETSCVIEWERDRAW,
1560            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType(),
1561            PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO()
1562 
1563   Level: beginner
1564 
1565 M*/
1566 
1567 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1568 {
1569   PetscErrorCode     ierr;
1570   PetscViewer_Binary *vbinary;
1571 
1572   PetscFunctionBegin;
1573   ierr    = PetscNewLog(v,&vbinary);CHKERRQ(ierr);
1574   v->data = (void*)vbinary;
1575 
1576   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
1577   v->ops->destroy          = PetscViewerDestroy_Binary;
1578   v->ops->view             = PetscViewerView_Binary;
1579   v->ops->setup            = PetscViewerSetUp_Binary;
1580   v->ops->flush            = NULL; /* Should we support Flush() ? */
1581   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
1582   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1583   v->ops->read             = PetscViewerBinaryRead;
1584 
1585   vbinary->fdes            = -1;
1586 #if defined(PETSC_HAVE_MPIIO)
1587   vbinary->usempiio        = PETSC_FALSE;
1588   vbinary->mfdes           = MPI_FILE_NULL;
1589   vbinary->mfsub           = MPI_FILE_NULL;
1590 #endif
1591   vbinary->filename        = NULL;
1592   vbinary->filemode        = FILE_MODE_UNDEFINED;
1593   vbinary->fdes_info       = NULL;
1594   vbinary->skipinfo        = PETSC_FALSE;
1595   vbinary->skipoptions     = PETSC_TRUE;
1596   vbinary->skipheader      = PETSC_FALSE;
1597   vbinary->storecompressed = PETSC_FALSE;
1598   vbinary->ogzfilename     = NULL;
1599   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */
1600 
1601   vbinary->setfromoptionscalled = PETSC_FALSE;
1602 
1603   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary);CHKERRQ(ierr);
1604   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary);CHKERRQ(ierr);
1605   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary);CHKERRQ(ierr);
1606   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary);CHKERRQ(ierr);
1607   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",PetscViewerBinaryGetSkipOptions_Binary);CHKERRQ(ierr);
1608   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",PetscViewerBinarySetSkipOptions_Binary);CHKERRQ(ierr);
1609   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",PetscViewerBinaryGetSkipInfo_Binary);CHKERRQ(ierr);
1610   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",PetscViewerBinarySetSkipInfo_Binary);CHKERRQ(ierr);
1611   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary);CHKERRQ(ierr);
1612   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary);CHKERRQ(ierr);
1613   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary);CHKERRQ(ierr);
1614   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary);CHKERRQ(ierr);
1615   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary);CHKERRQ(ierr);
1616 #if defined(PETSC_HAVE_MPIIO)
1617   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",PetscViewerBinaryGetUseMPIIO_Binary);CHKERRQ(ierr);
1618   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",PetscViewerBinarySetUseMPIIO_Binary);CHKERRQ(ierr);
1619 #endif
1620   PetscFunctionReturn(0);
1621 }
1622 
1623 /* ---------------------------------------------------------------------*/
1624 /*
1625     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1626   is attached to a communicator, in this case the attribute is a PetscViewer.
1627 */
1628 PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
1629 
1630 /*@C
1631      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
1632                      in a communicator.
1633 
1634      Collective
1635 
1636      Input Parameter:
1637 .    comm - the MPI communicator to share the binary PetscViewer
1638 
1639      Level: intermediate
1640 
1641    Options Database Keys:
1642 +    -viewer_binary_filename <name> - filename in which to store the binary data, defaults to binaryoutput
1643 .    -viewer_binary_skip_info - true means do not create .info file for this viewer
1644 .    -viewer_binary_skip_options - true means do not use the options database for this viewer
1645 .    -viewer_binary_skip_header - true means do not store the usual header information in the binary file
1646 -    -viewer_binary_mpiio - true means use the file via MPI-IO, maybe faster for large files and many MPI ranks
1647 
1648    Environmental variables:
1649 -   PETSC_VIEWER_BINARY_FILENAME - filename in which to store the binary data, defaults to binaryoutput
1650 
1651      Notes:
1652      Unlike almost all other PETSc routines, PETSC_VIEWER_BINARY_ does not return
1653      an error code.  The binary PetscViewer is usually used in the form
1654 $       XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));
1655 
1656 .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
1657           PetscViewerDestroy()
1658 @*/
1659 PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1660 {
1661   PetscErrorCode ierr;
1662   PetscBool      flg;
1663   PetscViewer    viewer;
1664   char           fname[PETSC_MAX_PATH_LEN];
1665   MPI_Comm       ncomm;
1666 
1667   PetscFunctionBegin;
1668   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1669   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1670     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,NULL);
1671     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1672   }
1673   ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
1674   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1675   if (!flg) { /* PetscViewer not yet created */
1676     ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1677     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
1678     if (!flg) {
1679       ierr = PetscStrcpy(fname,"binaryoutput");
1680       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
1681     }
1682     ierr = PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
1683     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
1684     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
1685     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
1686     ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
1687     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
1688   }
1689   ierr = PetscCommDestroy(&ncomm);
1690   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
1691   PetscFunctionReturn(viewer);
1692 }
1693