Actual source code: binv.c
1: /*$Id: binv.c,v 1.99 2001/04/10 19:34:06 bsmith Exp $*/
3: #include src/sys/src/viewer/viewerimpl.h
4: #include petscsys.h
5: #include <fcntl.h>
6: #if defined(PETSC_HAVE_UNISTD_H)
7: #include <unistd.h>
8: #endif
9: #if defined (PETSC_HAVE_IO_H)
10: #include <io.h>
11: #endif
13: typedef struct {
14: int fdes; /* file descriptor */
15: PetscViewerBinaryType btype; /* read or write? */
16: FILE *fdes_info; /* optional file containing info on binary file*/
17: PetscTruth storecompressed; /* gzip the write binary file when closing it*/
18: char *filename;
19: PetscTruth skipinfo; /* Don't create info file for writing */
20: } PetscViewer_Binary;
22: #undef __FUNCT__
24: int PetscViewerGetSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
25: {
26: int rank,ierr;
27: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data,*obinary;
30: MPI_Comm_rank(viewer->comm,&rank);
31: if (!rank) {
32: ierr = PetscViewerCreate(PETSC_COMM_SELF,outviewer);
33: ierr = PetscViewerSetType(*outviewer,PETSC_VIEWER_BINARY);
34: obinary = (PetscViewer_Binary*)(*outviewer)->data;
35: ierr = PetscMemcpy(obinary,vbinary,sizeof(PetscViewer_Binary));
36: } else {
37: *outviewer = 0;
38: }
39: return(0);
40: }
42: #undef __FUNCT__
44: int PetscViewerRestoreSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
45: {
46: int ierr,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: }
58: #undef __FUNCT__
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: int PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
85: {
86: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
89: *fdes = vbinary->fdes;
90: return(0);
91: }
93: #undef __FUNCT__
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: int PetscViewerBinarySkipInfo(PetscViewer viewer)
115: {
116: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
119: vbinary->skipinfo = PETSC_TRUE;
120: return(0);
121: }
123: #undef __FUNCT__
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: int PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
148: {
149: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
152: *file = vbinary->fdes_info;
153: return(0);
154: }
156: #undef __FUNCT__
158: int PetscViewerDestroy_Binary(PetscViewer v)
159: {
160: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
161: int ierr,rank;
164: MPI_Comm_rank(v->comm,&rank);
165: if (!rank && vbinary->fdes) {
166: close(vbinary->fdes);
167: if (vbinary->storecompressed) {
168: char par[PETSC_MAX_PATH_LEN],buf[PETSC_MAX_PATH_LEN];
169: FILE *fp;
170: /* compress the file */
171: PetscStrcpy(par,"gzip ");
172: PetscStrcat(par,vbinary->filename);
173: PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,par,"r",&fp);
174: if (fgets(buf,1024,fp)) {
175: SETERRQ2(1,"Error from command %sn%s",par,buf);
176: }
177: PetscPClose(PETSC_COMM_SELF,fp);
178: }
179: }
180: if (vbinary->fdes_info) fclose(vbinary->fdes_info);
181: PetscStrfree(vbinary->filename);
182: PetscFree(vbinary);
183: return(0);
184: }
186: #undef __FUNCT__
188: /*@C
189: PetscViewerBinaryOpen - Opens a file for binary input/output.
191: Collective on MPI_Comm
193: Input Parameters:
194: + comm - MPI communicator
195: . name - name of file
196: - type - type of file
197: $ PETSC_BINARY_CREATE - create new file for binary output
198: $ PETSC_BINARY_RDONLY - open existing file for binary input
199: $ PETSC_BINARY_WRONLY - open existing file for binary output
201: Output Parameter:
202: . binv - PetscViewer for binary input/output to use with the specified file
204: Level: beginner
206: Note:
207: This PetscViewer should be destroyed with PetscViewerDestroy().
209: For reading files, the filename may begin with ftp:// or http:// and/or
210: end with .gz; in this case file is brought over and uncompressed.
212: For creating files, if the file name ends with .gz it is automatically
213: compressed when closed.
215: For writing files it only opens the file on processor 0 in the communicator.
216: For readable files it opens the file on all nodes that have the file. If
217: node 0 does not have the file it generates an error even if other nodes
218: do have the file.
220: Concepts: binary files
221: Concepts: PetscViewerBinary^creating
222: Concepts: gzip
223: Concepts: accessing remote file
224: Concepts: remote file
226: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
227: VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
228: PetscViewerBinaryGetInfoPointer()
229: @*/
230: int PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscViewerBinaryType type,PetscViewer *binv)
231: {
233:
235: PetscViewerCreate(comm,binv);
236: PetscViewerSetType(*binv,PETSC_VIEWER_BINARY);
237: PetscViewerBinarySetType(*binv,type);
238: PetscViewerSetFilename(*binv,name);
239: return(0);
240: }
242: #undef __FUNCT__
244: /*@C
245: PetscViewerBinarySetType - Sets the type of binary file to be open
247: Collective on PetscViewer
249: Input Parameters:
250: + viewer - the PetscViewer; must be a binary PetscViewer
251: - type - type of file
252: $ PETSC_BINARY_CREATE - create new file for binary output
253: $ PETSC_BINARY_RDONLY - open existing file for binary input
254: $ PETSC_BINARY_WRONLY - open existing file for binary output
256: Level: advanced
258: .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
260: @*/
261: int PetscViewerBinarySetType(PetscViewer viewer,PetscViewerBinaryType type)
262: {
263: int ierr,(*f)(PetscViewer,PetscViewerBinaryType);
267: PetscObjectQueryFunction((PetscObject)viewer,"PetscViewerBinarySetType_C",(void (**)(void))&f);
268: if (f) {
269: (*f)(viewer,type);
270: }
272: return(0);
273: }
275: EXTERN_C_BEGIN
276: #undef __FUNCT__
278: int PetscViewerBinarySetType_Binary(PetscViewer viewer,PetscViewerBinaryType type)
279: {
280: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
283: vbinary->btype = type;
284: return(0);
285: }
286: EXTERN_C_END
288: #undef __FUNCT__
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: int PetscViewerBinaryLoadInfo(PetscViewer viewer)
303: {
304: FILE *file;
305: char string[256],*first,*second,*final;
306: int len,ierr;
307: PetscTruth flg;
308: PetscToken *token;
311: PetscOptionsHasName(PETSC_NULL,"-load_ignore_info",&flg);
312: if (flg) return(0);
314: PetscViewerBinaryGetInfoPointer(viewer,&file);
315: if (!file) return(0);
317: /* read rows of the file adding them to options database */
318: while (fgets(string,256,file)) {
319: /* Comments are indicated by #, ! or % in the first column */
320: if (string[0] == '#') continue;
321: if (string[0] == '!') continue;
322: if (string[0] == '%') continue;
323: PetscTokenCreate(string,' ',&token);
324: PetscTokenFind(token,&first);
325: PetscTokenFind(token,&second);
326: if (first && first[0] == '-') {
327: PetscTruth wrongtype;
328: /*
329: Check for -mat_complex or -mat_double
330: */
331: #if defined(PETSC_USE_COMPLEX)
332: PetscStrncmp(first,"-mat_double",11,&wrongtype);
333: if (wrongtype) {
334: SETERRQ(1,"Loading double number matrix with complex number code");
335: }
336: #else
337: PetscStrncmp(first,"-mat_complex",12,&wrongtype);
338: if (wrongtype) {
339: SETERRQ(1,"Loading complex number matrix with double number code");
340: }
341: #endif
343: if (second) {final = second;} else {final = first;}
344: PetscStrlen(final,&len);
345: while (len > 0 && (final[len-1] == ' ' || final[len-1] == 'n')) {
346: len--; final[len] = 0;
347: }
348: PetscOptionsSetValue(first,second);
349: }
350: PetscTokenDestroy(token);
351: }
352: return(0);
354: }
356: /*
357: Actually opens the file
358: */
359: EXTERN_C_BEGIN
360: #undef __FUNCT__
362: int PetscViewerSetFilename_Binary(PetscViewer viewer,const char name[])
363: {
364: int rank,ierr,len;
365: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
366: const char *fname;
367: char bname[PETSC_MAX_PATH_LEN],*gz;
368: PetscTruth found;
369: PetscViewerBinaryType type = vbinary->btype;
372: if (type == (PetscViewerBinaryType) -1) {
373: SETERRQ(1,"Must call PetscViewerBinarySetType() before PetscViewerSetFilename()");
374: }
375: PetscOptionsHasName(viewer->prefix,"-viewer_binary_skip_info",&vbinary->skipinfo);
377: MPI_Comm_rank(viewer->comm,&rank);
379: /* copy name so we can edit it */
380: PetscStrallocpy(name,&vbinary->filename);
382: /* if ends in .gz strip that off and note user wants file compressed */
383: vbinary->storecompressed = PETSC_FALSE;
384: if (!rank && type == PETSC_BINARY_CREATE) {
385: /* remove .gz if it ends library name */
386: PetscStrstr(vbinary->filename,".gz",&gz);
387: if (gz) {
388: PetscStrlen(gz,&len);
389: if (len == 3) {
390: *gz = 0;
391: vbinary->storecompressed = PETSC_TRUE;
392: }
393: }
394: }
396: /* only first processor opens file if writeable */
397: if (!rank || type == PETSC_BINARY_RDONLY) {
399: if (type == PETSC_BINARY_RDONLY){
400: /* possibly get the file from remote site or compressed file */
401: ierr = PetscFileRetrieve(viewer->comm,vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);
402: fname = bname;
403: if (!rank && !found) {
404: SETERRQ1(1,"Cannot locate file: %s on node zero",vbinary->filename);
405: } else if (!found) {
406: PetscLogInfo(viewer,"Nonzero processor did not locate readonly file");
407: fname = 0;
408: }
409: } else {
410: fname = vbinary->filename;
411: }
413: #if defined(PARCH_win32_gnu) || defined(PARCH_win32)
414: if (type == PETSC_BINARY_CREATE) {
415: if ((vbinary->fdes = open(fname,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
416: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
417: }
418: } else if (type == PETSC_BINARY_RDONLY && fname) {
419: if ((vbinary->fdes = open(fname,O_RDONLY|O_BINARY,0)) == -1) {
420: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
421: }
422: } else if (type == PETSC_BINARY_WRONLY) {
423: if ((vbinary->fdes = open(fname,O_WRONLY|O_BINARY,0)) == -1) {
424: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
425: }
426: } else if (fname) {
427: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
428: }
429: #else
430: if (type == PETSC_BINARY_CREATE) {
431: if ((vbinary->fdes = creat(fname,0666)) == -1) {
432: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
433: }
434: } else if (type == PETSC_BINARY_RDONLY && fname) {
435: if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) {
436: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
437: }
438: } else if (type == PETSC_BINARY_WRONLY) {
439: if ((vbinary->fdes = open(fname,O_WRONLY|O_APPEND,0)) == -1) {
440: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
441: }
442: } else if (fname) {
443: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
444: }
445: #endif
446: } else vbinary->fdes = -1;
447: viewer->format = PETSC_VIEWER_NOFORMAT;
449: /*
450: try to open info file: all processors open this file if read only
451: */
452: if (!rank || type == PETSC_BINARY_RDONLY) {
453: char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];
454:
455: PetscStrcpy(infoname,name);
456: /* remove .gz if it ends library name */
457: PetscStrstr(infoname,".gz",&gz);
458: if (gz) {
459: PetscStrlen(gz,&len);
460: if (len == 3) {
461: *gz = 0;
462: }
463: }
464:
465: PetscStrcat(infoname,".info");
466: PetscFixFilename(infoname,iname);
467: if (type == PETSC_BINARY_RDONLY) {
468: PetscFileRetrieve(viewer->comm,iname,infoname,PETSC_MAX_PATH_LEN,&found);
469: if (found) {
470: vbinary->fdes_info = fopen(infoname,"r");
471: if (vbinary->fdes_info) {
472: PetscViewerBinaryLoadInfo(viewer);
473: fclose(vbinary->fdes_info);
474: }
475: vbinary->fdes_info = fopen(infoname,"r");
476: }
477: } else if (!vbinary->skipinfo) {
478: vbinary->fdes_info = fopen(infoname,"w");
479: if (!vbinary->fdes_info) {
480: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
481: }
482: }
483: }
485: #if defined(PETSC_USE_LOG)
486: PetscLogObjectState((PetscObject)viewer,"File: %s",name);
487: #endif
488: return(0);
489: }
490: EXTERN_C_END
492: EXTERN_C_BEGIN
493: #undef __FUNCT__
495: int PetscViewerCreate_Binary(PetscViewer v)
496: {
497: int ierr;
498: PetscViewer_Binary *vbinary;
501: ierr = PetscNew(PetscViewer_Binary,&vbinary);
502: v->data = (void*)vbinary;
503: v->ops->destroy = PetscViewerDestroy_Binary;
504: v->ops->flush = 0;
505: v->iformat = 0;
506: vbinary->fdes_info = 0;
507: vbinary->fdes = 0;
508: vbinary->skipinfo = PETSC_FALSE;
509: v->ops->getsingleton = PetscViewerGetSingleton_Binary;
510: v->ops->restoresingleton = PetscViewerRestoreSingleton_Binary;
511: vbinary->btype = (PetscViewerBinaryType) -1;
512: vbinary->storecompressed = PETSC_FALSE;
513: vbinary->filename = 0;
515: PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerSetFilename_C",
516: "PetscViewerSetFilename_Binary",
517: PetscViewerSetFilename_Binary);
518: PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerBinarySetType_C",
519: "PetscViewerBinarySetType_Binary",
520: PetscViewerBinarySetType_Binary);
521: return(0);
522: }
523: EXTERN_C_END
526: /* ---------------------------------------------------------------------*/
527: /*
528: The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
529: is attached to a communicator, in this case the attribute is a PetscViewer.
530: */
531: static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
533: /*MC
534: PETSC_VIEWER_BINARY_WORLD - same as PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD)
536: Level: intermediate
537: M*/
539: /*MC
540: PETSC_VIEWER_BINARY_SELF - same as PETSC_VIEWER_BINARY_(PETSC_COMM_SELF)
542: Level: intermediate
543: M*/
546: #undef __FUNCT__
548: /*@C
549: PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
550: in a communicator.
552: Collective on MPI_Comm
554: Input Parameter:
555: . comm - the MPI communicator to share the binary PetscViewer
556:
557: Level: intermediate
559: Options Database Keys:
560: $ -viewer_binary_filename <name>
562: Environmental variables:
563: - PETSC_VIEWER_BINARY_FILENAME
565: Notes:
566: Unlike almost all other PETSc routines, PETSC_VIEWER_BINARY_ does not return
567: an error code. The binary PetscViewer is usually used in the form
568: $ XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));
570: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
571: PetscViewerDestroy()
572: @*/
573: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
574: {
575: int ierr;
576: PetscTruth flg;
577: PetscViewer viewer;
578: char fname[PETSC_MAX_PATH_LEN];
581: if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
582: MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
583: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
584: }
585: MPI_Attr_get(comm,Petsc_Viewer_Binary_keyval,(void **)&viewer,(int *)&flg);
586: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
587: if (!flg) { /* PetscViewer not yet created */
588: PetscOptionsGetenv(comm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
589: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
590: if (!flg) {
591: PetscStrcpy(fname,"binaryoutput");
592: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
593: }
594: PetscViewerBinaryOpen(comm,fname,PETSC_BINARY_CREATE,&viewer);
595: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
596: PetscObjectRegisterDestroy((PetscObject)viewer);
597: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_STDOUT_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
598: MPI_Attr_put(comm,Petsc_Viewer_Binary_keyval,(void*)viewer);
599: if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
600: }
601: PetscFunctionReturn(viewer);
602: }