Actual source code: binv.c
1: #include "src/sys/src/viewer/viewerimpl.h" /*I "petsc.h" I*/
2: #include petscsys.h
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
11: typedef struct {
12: int fdes; /* file descriptor */
13: PetscViewerFileType btype; /* read or write? */
14: FILE *fdes_info; /* optional file containing info on binary file*/
15: PetscTruth storecompressed; /* gzip the write binary file when closing it*/
16: char *filename;
17: PetscTruth skipinfo; /* Don't create info file for writing */
18: } PetscViewer_Binary;
22: PetscErrorCode PetscViewerGetSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
23: {
24: int rank;
25: PetscErrorCode ierr;
26: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data,*obinary;
29: MPI_Comm_rank(viewer->comm,&rank);
30: if (!rank) {
31: PetscViewerCreate(PETSC_COMM_SELF,outviewer);
32: PetscViewerSetType(*outviewer,PETSC_VIEWER_BINARY);
33: obinary = (PetscViewer_Binary*)(*outviewer)->data;
34: PetscMemcpy(obinary,vbinary,sizeof(PetscViewer_Binary));
35: } else {
36: *outviewer = 0;
37: }
38: return(0);
39: }
43: PetscErrorCode PetscViewerRestoreSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
44: {
46: PetscErrorCode rank;
49: MPI_Comm_rank(viewer->comm,&rank);
50: if (!rank) {
51: PetscFree((*outviewer)->data);
52: PetscLogObjectDestroy((PetscObject)*outviewer);
53: PetscHeaderDestroy((PetscObject)*outviewer);
54: }
55: return(0);
56: }
60: /*@C
61: PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.
63: Not Collective
65: + viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
66: - fdes - file descriptor
68: Level: advanced
70: Notes:
71: For writable binary PetscViewers, the descriptor will only be valid for the
72: first processor in the communicator that shares the PetscViewer. For readable
73: files it will only be valid on nodes that have the file. If node 0 does not
74: have the file it generates an error even if another node does have the file.
75:
76: Fortran Note:
77: This routine is not supported in Fortran.
79: Concepts: file descriptor^getting
80: Concepts: PetscViewerBinary^accessing file descriptor
82: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
83: @*/
84: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
85: {
86: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
89: *fdes = vbinary->fdes;
90: return(0);
91: }
95: /*@
96: PetscViewerBinarySkipInfo - Binary file will not have .info file created with it
98: Not Collective
100: Input Paramter:
101: . viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
103: Options Database Key:
104: . -viewer_binary_skip_info
106: Level: advanced
108: Notes: This must be called after PetscViewerSetType() but before PetscViewerBinarySetFilename()
110: Concepts: PetscViewerBinary^accessing info file
112: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
113: @*/
114: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
115: {
116: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
119: vbinary->skipinfo = PETSC_TRUE;
120: return(0);
121: }
125: /*@C
126: PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
127: info file associated with a binary file.
129: Not Collective
131: + viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
132: - file - file pointer
134: Level: advanced
136: Notes:
137: For writable binary PetscViewers, the descriptor will only be valid for the
138: first processor in the communicator that shares the PetscViewer.
139:
140: Fortran Note:
141: This routine is not supported in Fortran.
143: Concepts: PetscViewerBinary^accessing info file
145: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
146: @*/
147: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
148: {
149: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
152: *file = vbinary->fdes_info;
153: return(0);
154: }
158: PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
159: {
160: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
161: PetscErrorCode ierr;
162: int rank;
165: MPI_Comm_rank(v->comm,&rank);
166: if ((!rank || vbinary->btype == PETSC_FILE_RDONLY ) && vbinary->fdes) {
167: close(vbinary->fdes);
168: if (!rank && vbinary->storecompressed) {
169: char par[PETSC_MAX_PATH_LEN],buf[PETSC_MAX_PATH_LEN];
170: FILE *fp;
171: /* compress the file */
172: PetscStrcpy(par,"gzip ");
173: PetscStrcat(par,vbinary->filename);
174: PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,par,"r",&fp);
175: if (fgets(buf,1024,fp)) {
176: SETERRQ2(PETSC_ERR_LIB,"Error from command %s\n%s",par,buf);
177: }
178: PetscPClose(PETSC_COMM_SELF,fp);
179: }
180: }
181: if (vbinary->fdes_info) fclose(vbinary->fdes_info);
182: PetscStrfree(vbinary->filename);
183: PetscFree(vbinary);
184: return(0);
185: }
189: /*@C
190: PetscViewerBinaryOpen - Opens a file for binary input/output.
192: Collective on MPI_Comm
194: Input Parameters:
195: + comm - MPI communicator
196: . name - name of file
197: - type - type of file
198: $ PETSC_FILE_CREATE - create new file for binary output
199: $ PETSC_FILE_RDONLY - open existing file for binary input
200: $ PETSC_FILE_WRONLY - open existing file for binary output
202: Output Parameter:
203: . binv - PetscViewer for binary input/output to use with the specified file
205: Level: beginner
207: Note:
208: This PetscViewer should be destroyed with PetscViewerDestroy().
210: For reading files, the filename may begin with ftp:// or http:// and/or
211: end with .gz; in this case file is brought over and uncompressed.
213: For creating files, if the file name ends with .gz it is automatically
214: compressed when closed.
216: For writing files it only opens the file on processor 0 in the communicator.
217: For readable files it opens the file on all nodes that have the file. If
218: node 0 does not have the file it generates an error even if other nodes
219: do have the file.
221: Concepts: binary files
222: Concepts: PetscViewerBinary^creating
223: Concepts: gzip
224: Concepts: accessing remote file
225: Concepts: remote file
227: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
228: VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
229: PetscViewerBinaryGetInfoPointer(), PetscViewerFileType, PetscViewer
230: @*/
231: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscViewerFileType type,PetscViewer *binv)
232: {
234:
236: PetscViewerCreate(comm,binv);
237: PetscViewerSetType(*binv,PETSC_VIEWER_BINARY);
238: PetscViewerSetFileType(*binv,type);
239: PetscViewerSetFilename(*binv,name);
240: return(0);
241: }
245: /*@C
246: PetscViewerSetFileType - Sets the type of file to be open
248: Collective on PetscViewer
250: Input Parameters:
251: + viewer - the PetscViewer; must be a binary, Matlab, hdf, or netcdf PetscViewer
252: - type - type of file
253: $ PETSC_FILE_CREATE - create new file for binary output
254: $ PETSC_FILE_RDONLY - open existing file for binary input
255: $ PETSC_FILE_WRONLY - open existing file for binary output
257: Level: advanced
259: .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
261: @*/
262: PetscErrorCode PetscViewerSetFileType(PetscViewer viewer,PetscViewerFileType type)
263: {
264: PetscErrorCode ierr,(*f)(PetscViewer,PetscViewerFileType);
268: PetscObjectQueryFunction((PetscObject)viewer,"PetscViewerSetFileType_C",(void (**)(void))&f);
269: if (f) {
270: (*f)(viewer,type);
271: }
272: return(0);
273: }
278: PetscErrorCode PetscViewerSetFileType_Binary(PetscViewer viewer,PetscViewerFileType type)
279: {
280: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
283: vbinary->btype = type;
284: return(0);
285: }
290: /*@
291: PetscViewerBinaryLoadInfo - Loads options from the name.info file
292: if it exists.
294: Collective on PetscViewer
296: Input Parameter:
297: . viewer - the binary viewer whose options you wish to load
299: Level: developer
301: @*/
302: PetscErrorCode PetscViewerBinaryLoadInfo(PetscViewer viewer)
303: {
304: FILE *file;
305: char string[256],*first,*second,*final;
306: size_t len;
308: PetscTruth flg;
309: PetscToken *token;
312: PetscOptionsHasName(PETSC_NULL,"-load_ignore_info",&flg);
313: if (flg) return(0);
315: PetscViewerBinaryGetInfoPointer(viewer,&file);
316: if (!file) return(0);
318: /* read rows of the file adding them to options database */
319: while (fgets(string,256,file)) {
320: /* Comments are indicated by #, ! or % in the first column */
321: if (string[0] == '#') continue;
322: if (string[0] == '!') continue;
323: if (string[0] == '%') continue;
324: PetscTokenCreate(string,' ',&token);
325: PetscTokenFind(token,&first);
326: PetscTokenFind(token,&second);
327: if (first && first[0] == '-') {
328: PetscTruth wrongtype;
329: /*
330: Check for -mat_complex or -mat_double
331: */
332: #if defined(PETSC_USE_COMPLEX)
333: PetscStrncmp(first,"-mat_double",11,&wrongtype);
334: if (wrongtype) {
335: SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Loading double number matrix with complex number code");
336: }
337: #else
338: PetscStrncmp(first,"-mat_complex",12,&wrongtype);
339: if (wrongtype) {
340: SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Loading complex number matrix with double number code");
341: }
342: #endif
344: if (second) {final = second;} else {final = first;}
345: PetscStrlen(final,&len);
346: while (len > 0 && (final[len-1] == ' ' || final[len-1] == '\n')) {
347: len--; final[len] = 0;
348: }
349: PetscOptionsSetValue(first,second);
350: }
351: PetscTokenDestroy(token);
352: }
353: return(0);
354: }
356: /*
357: Actually opens the file
358: */
362: PetscErrorCode PetscViewerSetFilename_Binary(PetscViewer viewer,const char name[])
363: {
364: int rank;
365: PetscErrorCode ierr;
366: size_t len;
367: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
368: const char *fname;
369: char bname[PETSC_MAX_PATH_LEN],*gz;
370: PetscTruth found;
371: PetscViewerFileType type = vbinary->btype;
374: if (type == (PetscViewerFileType) -1) {
375: SETERRQ(PETSC_ERR_ORDER,"Must call PetscViewerBinarySetType() before PetscViewerSetFilename()");
376: }
377: PetscOptionsHasName(viewer->prefix,"-viewer_binary_skip_info",&vbinary->skipinfo);
379: MPI_Comm_rank(viewer->comm,&rank);
381: /* copy name so we can edit it */
382: PetscStrallocpy(name,&vbinary->filename);
384: /* if ends in .gz strip that off and note user wants file compressed */
385: vbinary->storecompressed = PETSC_FALSE;
386: if (!rank && type == PETSC_FILE_CREATE) {
387: /* remove .gz if it ends library name */
388: PetscStrstr(vbinary->filename,".gz",&gz);
389: if (gz) {
390: PetscStrlen(gz,&len);
391: if (len == 3) {
392: *gz = 0;
393: vbinary->storecompressed = PETSC_TRUE;
394: }
395: }
396: }
398: /* only first processor opens file if writeable */
399: if (!rank || type == PETSC_FILE_RDONLY) {
401: if (type == PETSC_FILE_RDONLY){
402: /* possibly get the file from remote site or compressed file */
403: PetscFileRetrieve(viewer->comm,vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);
404: fname = bname;
405: if (!rank && !found) {
406: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
407: } else if (!found) {
408: PetscLogInfo(viewer,"Nonzero processor did not locate readonly file");
409: fname = 0;
410: }
411: } else {
412: fname = vbinary->filename;
413: }
415: #if defined(PETSC_HAVE_O_BINARY)
416: if (type == PETSC_FILE_CREATE) {
417: if ((vbinary->fdes = open(fname,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
418: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
419: }
420: } else if (type == PETSC_FILE_RDONLY && fname) {
421: if ((vbinary->fdes = open(fname,O_RDONLY|O_BINARY,0)) == -1) {
422: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
423: }
424: } else if (type == PETSC_FILE_WRONLY) {
425: if ((vbinary->fdes = open(fname,O_WRONLY|O_BINARY,0)) == -1) {
426: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
427: }
428: } else if (fname) {
429: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
430: }
431: #else
432: if (type == PETSC_FILE_CREATE) {
433: if ((vbinary->fdes = creat(fname,0666)) == -1) {
434: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
435: }
436: } else if (type == PETSC_FILE_RDONLY && fname) {
437: if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) {
438: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
439: }
440: } else if (type == PETSC_FILE_WRONLY) {
441: if ((vbinary->fdes = open(fname,O_WRONLY|O_APPEND,0)) == -1) {
442: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
443: }
444: } else if (fname) {
445: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
446: }
447: #endif
448: } else vbinary->fdes = -1;
449: viewer->format = PETSC_VIEWER_NOFORMAT;
451: /*
452: try to open info file: all processors open this file if read only
453: */
454: if (!rank || type == PETSC_FILE_RDONLY) {
455: char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];
456:
457: PetscStrcpy(infoname,name);
458: /* remove .gz if it ends library name */
459: PetscStrstr(infoname,".gz",&gz);
460: if (gz) {
461: PetscStrlen(gz,&len);
462: if (len == 3) {
463: *gz = 0;
464: }
465: }
466:
467: PetscStrcat(infoname,".info");
468: PetscFixFilename(infoname,iname);
469: if (type == PETSC_FILE_RDONLY) {
470: PetscFileRetrieve(viewer->comm,iname,infoname,PETSC_MAX_PATH_LEN,&found);
471: if (found) {
472: vbinary->fdes_info = fopen(infoname,"r");
473: if (vbinary->fdes_info) {
474: PetscViewerBinaryLoadInfo(viewer);
475: fclose(vbinary->fdes_info);
476: }
477: vbinary->fdes_info = fopen(infoname,"r");
478: }
479: } else if (!vbinary->skipinfo) {
480: vbinary->fdes_info = fopen(infoname,"w");
481: if (!vbinary->fdes_info) {
482: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
483: }
484: }
485: }
487: #if defined(PETSC_USE_LOG)
488: PetscLogObjectState((PetscObject)viewer,"File: %s",name);
489: #endif
490: return(0);
491: }
497: PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
498: {
499: PetscErrorCode ierr;
500: PetscViewer_Binary *vbinary;
503: PetscNew(PetscViewer_Binary,&vbinary);
504: v->data = (void*)vbinary;
505: v->ops->destroy = PetscViewerDestroy_Binary;
506: v->ops->flush = 0;
507: v->iformat = 0;
508: vbinary->fdes_info = 0;
509: vbinary->fdes = 0;
510: vbinary->skipinfo = PETSC_FALSE;
511: v->ops->getsingleton = PetscViewerGetSingleton_Binary;
512: v->ops->restoresingleton = PetscViewerRestoreSingleton_Binary;
513: vbinary->btype = (PetscViewerFileType) -1;
514: vbinary->storecompressed = PETSC_FALSE;
515: vbinary->filename = 0;
517: PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerSetFilename_C",
518: "PetscViewerSetFilename_Binary",
519: PetscViewerSetFilename_Binary);
520: PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerSetFileType_C",
521: "PetscViewerSetFileType_Binary",
522: PetscViewerSetFileType_Binary);
523: return(0);
524: }
528: /* ---------------------------------------------------------------------*/
529: /*
530: The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
531: is attached to a communicator, in this case the attribute is a PetscViewer.
532: */
533: static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
537: /*@C
538: PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
539: in a communicator.
541: Collective on MPI_Comm
543: Input Parameter:
544: . comm - the MPI communicator to share the binary PetscViewer
545:
546: Level: intermediate
548: Options Database Keys:
549: $ -viewer_binary_filename <name>
551: Environmental variables:
552: - PETSC_VIEWER_BINARY_FILENAME
554: Notes:
555: Unlike almost all other PETSc routines, PETSC_VIEWER_BINARY_ does not return
556: an error code. The binary PetscViewer is usually used in the form
557: $ XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));
559: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
560: PetscViewerDestroy()
561: @*/
562: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
563: {
565: PetscTruth flg;
566: PetscViewer viewer;
567: char fname[PETSC_MAX_PATH_LEN];
570: if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
571: MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
572: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
573: }
574: MPI_Attr_get(comm,Petsc_Viewer_Binary_keyval,(void **)&viewer,(int*)&flg);
575: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
576: if (!flg) { /* PetscViewer not yet created */
577: PetscOptionsGetenv(comm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
578: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
579: if (!flg) {
580: PetscStrcpy(fname,"binaryoutput");
581: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
582: }
583: PetscViewerBinaryOpen(comm,fname,PETSC_FILE_CREATE,&viewer);
584: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
585: PetscObjectRegisterDestroy((PetscObject)viewer);
586: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
587: MPI_Attr_put(comm,Petsc_Viewer_Binary_keyval,(void*)viewer);
588: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
589: }
590: PetscFunctionReturn(viewer);
591: }