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: int PetscViewerGetSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
23: {
24: int rank,ierr;
25: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data,*obinary;
28: MPI_Comm_rank(viewer->comm,&rank);
29: if (!rank) {
30: ierr = PetscViewerCreate(PETSC_COMM_SELF,outviewer);
31: ierr = PetscViewerSetType(*outviewer,PETSC_VIEWER_BINARY);
32: obinary = (PetscViewer_Binary*)(*outviewer)->data;
33: ierr = PetscMemcpy(obinary,vbinary,sizeof(PetscViewer_Binary));
34: } else {
35: *outviewer = 0;
36: }
37: return(0);
38: }
40: int PetscViewerRestoreSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
41: {
42: int ierr,rank;
45: MPI_Comm_rank(viewer->comm,&rank);
46: if (!rank) {
47: PetscFree((*outviewer)->data);
48: PetscLogObjectDestroy((PetscObject)*outviewer);
49: PetscHeaderDestroy((PetscObject)*outviewer);
50: }
51: return(0);
52: }
54: /*@C
55: PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.
57: Not Collective
59: + viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
60: - fdes - file descriptor
62: Level: advanced
64: Notes:
65: For writable binary PetscViewers, the descriptor will only be valid for the
66: first processor in the communicator that shares the PetscViewer. For readable
67: files it will only be valid on nodes that have the file. If node 0 does not
68: have the file it generates an error even if another node does have the file.
69:
70: Fortran Note:
71: This routine is not supported in Fortran.
73: Concepts: file descriptor^getting
74: Concepts: PetscViewerBinary^accessing file descriptor
76: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
77: @*/
78: int PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
79: {
80: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
83: *fdes = vbinary->fdes;
84: return(0);
85: }
87: /*@
88: PetscViewerBinarySkipInfo - Binary file will not have .info file created with it
90: Not Collective
92: Input Paramter:
93: . viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
95: Options Database:
96: . -viewer_binary_skip_info
98: Level: advanced
100: Notes: This must be called after PetscViewerSetType() but before PetscViewerBinarySetFilename()
102: Concepts: PetscViewerBinary^accessing info file
104: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
105: @*/
106: int PetscViewerBinarySkipInfo(PetscViewer viewer)
107: {
108: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
111: vbinary->skipinfo = PETSC_TRUE;
112: return(0);
113: }
115: /*@C
116: PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
117: info file associated with a binary file.
119: Not Collective
121: + viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
122: - file - file pointer
124: Level: advanced
126: Notes:
127: For writable binary PetscViewers, the descriptor will only be valid for the
128: first processor in the communicator that shares the PetscViewer.
129:
130: Fortran Note:
131: This routine is not supported in Fortran.
133: Concepts: PetscViewerBinary^accessing info file
135: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
136: @*/
137: int PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
138: {
139: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
142: *file = vbinary->fdes_info;
143: return(0);
144: }
146: int PetscViewerDestroy_Binary(PetscViewer v)
147: {
148: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
149: int ierr,rank;
152: MPI_Comm_rank(v->comm,&rank);
153: if (!rank && vbinary->fdes) {
154: close(vbinary->fdes);
155: if (vbinary->storecompressed) {
156: char par[1024],buf[1024];
157: FILE *fp;
158: /* compress the file */
159: PetscStrcpy(par,"gzip ");
160: PetscStrcat(par,vbinary->filename);
161: PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,par,"r",&fp);
162: if (fgets(buf,1024,fp)) {
163: SETERRQ2(1,"Error from command %sn%s",par,buf);
164: }
165: PetscPClose(PETSC_COMM_SELF,fp);
166: }
167: }
168: if (vbinary->fdes_info) fclose(vbinary->fdes_info);
169: PetscStrfree(vbinary->filename);
170: PetscFree(vbinary);
171: return(0);
172: }
174: /*@C
175: PetscViewerBinaryOpen - Opens a file for binary input/output.
177: Collective on MPI_Comm
179: Input Parameters:
180: + comm - MPI communicator
181: . name - name of file
182: - type - type of file
183: $ PETSC_BINARY_CREATE - create new file for binary output
184: $ PETSC_BINARY_RDONLY - open existing file for binary input
185: $ PETSC_BINARY_WRONLY - open existing file for binary output
187: Output Parameter:
188: . binv - PetscViewer for binary input/output to use with the specified file
190: Level: beginner
192: Note:
193: This PetscViewer should be destroyed with PetscViewerDestroy().
195: For reading files, the filename may begin with ftp:// or http:// and/or
196: end with .gz; in this case file is brought over and uncompressed.
198: For creating files, if the file name ends with .gz it is automatically
199: compressed when closed.
201: For writing files it only opens the file on processor 0 in the communicator.
202: For readable files it opens the file on all nodes that have the file. If
203: node 0 does not have the file it generates an error even if other nodes
204: do have the file.
206: Concepts: binary files
207: Concepts: PetscViewerBinary^creating
208: Concepts: gzip
209: Concepts: accessing remote file
210: Concepts: remote file
212: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
213: VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
214: PetscViewerBinaryGetInfoPointer()
215: @*/
216: int PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscViewerBinaryType type,PetscViewer *binv)
217: {
219:
221: PetscViewerCreate(comm,binv);
222: PetscViewerSetType(*binv,PETSC_VIEWER_BINARY);
223: PetscViewerBinarySetType(*binv,type);
224: PetscViewerSetFilename(*binv,name);
225: return(0);
226: }
228: /*@C
229: PetscViewerBinarySetType - Sets the type of binary file to be open
231: Collective on PetscViewer
233: Input Parameters:
234: + viewer - the PetscViewer; must be a binary PetscViewer
235: - type - type of file
236: $ PETSC_BINARY_CREATE - create new file for binary output
237: $ PETSC_BINARY_RDONLY - open existing file for binary input
238: $ PETSC_BINARY_WRONLY - open existing file for binary output
240: Level: advanced
242: .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
244: @*/
245: int PetscViewerBinarySetType(PetscViewer viewer,PetscViewerBinaryType type)
246: {
247: int ierr,(*f)(PetscViewer,PetscViewerBinaryType);
251: PetscObjectQueryFunction((PetscObject)viewer,"PetscViewerBinarySetType_C",(void (**)(void))&f);
252: if (f) {
253: (*f)(viewer,type);
254: }
256: return(0);
257: }
259: EXTERN_C_BEGIN
260: int PetscViewerBinarySetType_Binary(PetscViewer viewer,PetscViewerBinaryType type)
261: {
262: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
265: vbinary->btype = type;
266: return(0);
267: }
268: EXTERN_C_END
270: /*
271: PetscViewerBinaryLoadInfo options from the name.info file
272: if it exists.
273: */
274: int PetscViewerBinaryLoadInfo(PetscViewer viewer)
275: {
276: FILE *file;
277: char string[128],*first,*second,*final;
278: int len,ierr;
279: PetscTruth flg;
280: PetscToken *token;
283: PetscOptionsHasName(PETSC_NULL,"-load_ignore_info",&flg);
284: if (flg) return(0);
286: PetscViewerBinaryGetInfoPointer(viewer,&file);
287: if (!file) return(0);
289: /* read rows of the file adding them to options database */
290: while (fgets(string,128,file)) {
291: /* Comments are indicated by #, ! or % in the first column */
292: if (string[0] == '#') continue;
293: if (string[0] == '!') continue;
294: if (string[0] == '%') continue;
295: PetscTokenCreate(string,' ',&token);
296: PetscTokenFind(token,&first);
297: PetscTokenFind(token,&second);
298: if (first && first[0] == '-') {
299: PetscTruth wrongtype;
300: /*
301: Check for -mat_complex or -mat_double
302: */
303: #if defined(PETSC_USE_COMPLEX)
304: PetscStrncmp(first,"-mat_double",11,&wrongtype);
305: if (wrongtype) {
306: SETERRQ(1,"Loading double number matrix with complex number code");
307: }
308: #else
309: PetscStrncmp(first,"-mat_complex",12,&wrongtype);
310: if (wrongtype) {
311: SETERRQ(1,"Loading complex number matrix with double number code");
312: }
313: #endif
315: if (second) {final = second;} else {final = first;}
316: PetscStrlen(final,&len);
317: while (len > 0 && (final[len-1] == ' ' || final[len-1] == 'n')) {
318: len--; final[len] = 0;
319: }
320: PetscOptionsSetValue(first,second);
321: }
322: PetscTokenDestroy(token);
323: }
324: return(0);
326: }
328: /*
329: Actually opens the file
330: */
331: EXTERN_C_BEGIN
332: int PetscViewerSetFilename_Binary(PetscViewer viewer,const char name[])
333: {
334: int rank,ierr,len;
335: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
336: const char *fname;
337: char bname[1024],*gz;
338: PetscTruth found;
339: PetscViewerBinaryType type = vbinary->btype;
342: if (type == (PetscViewerBinaryType) -1) {
343: SETERRQ(1,"Must call PetscViewerBinarySetType() before PetscViewerSetFilename()");
344: }
345: PetscOptionsHasName(viewer->prefix,"-viewer_binary_skip_info",&vbinary->skipinfo);
347: MPI_Comm_rank(viewer->comm,&rank);
349: /* copy name so we can edit it */
350: PetscStrallocpy(name,&vbinary->filename);
352: /* if ends in .gz strip that off and note user wants file compressed */
353: vbinary->storecompressed = PETSC_FALSE;
354: if (!rank && type == PETSC_BINARY_CREATE) {
355: /* remove .gz if it ends library name */
356: PetscStrstr(vbinary->filename,".gz",&gz);
357: if (gz) {
358: PetscStrlen(gz,&len);
359: if (len == 3) {
360: *gz = 0;
361: vbinary->storecompressed = PETSC_TRUE;
362: }
363: }
364: }
366: /* only first processor opens file if writeable */
367: if (!rank || type == PETSC_BINARY_RDONLY) {
369: if (type == PETSC_BINARY_RDONLY){
370: /* possibly get the file from remote site or compressed file */
371: ierr = PetscFileRetrieve(viewer->comm,vbinary->filename,bname,1024,&found);
372: fname = bname;
373: if (!rank && !found) {
374: SETERRQ1(1,"Cannot locate file: %s on node zero",vbinary->filename);
375: } else if (!found) {
376: PetscLogInfo(viewer,"Nonzero processor did not locate readonly file");
377: fname = 0;
378: }
379: } else {
380: fname = vbinary->filename;
381: }
383: #if defined(PARCH_win32_gnu) || defined(PARCH_win32)
384: if (type == PETSC_BINARY_CREATE) {
385: if ((vbinary->fdes = open(fname,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
386: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
387: }
388: } else if (type == PETSC_BINARY_RDONLY && fname) {
389: if ((vbinary->fdes = open(fname,O_RDONLY|O_BINARY,0)) == -1) {
390: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
391: }
392: } else if (type == PETSC_BINARY_WRONLY) {
393: if ((vbinary->fdes = open(fname,O_WRONLY|O_BINARY,0)) == -1) {
394: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
395: }
396: } else if (fname) {
397: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
398: }
399: #else
400: if (type == PETSC_BINARY_CREATE) {
401: if ((vbinary->fdes = creat(fname,0666)) == -1) {
402: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
403: }
404: } else if (type == PETSC_BINARY_RDONLY && fname) {
405: if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) {
406: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
407: }
408: } else if (type == PETSC_BINARY_WRONLY) {
409: if ((vbinary->fdes = open(fname,O_WRONLY,0)) == -1) {
410: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
411: }
412: } else if (fname) {
413: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
414: }
415: #endif
416: } else vbinary->fdes = -1;
417: viewer->format = PETSC_VIEWER_NOFORMAT;
419: /*
420: try to open info file: all processors open this file if read only
421: */
422: if (!rank || type == PETSC_BINARY_RDONLY) {
423: char infoname[256],iname[256];
424:
425: PetscStrcpy(infoname,name);
426: /* remove .gz if it ends library name */
427: PetscStrstr(infoname,".gz",&gz);
428: if (gz) {
429: PetscStrlen(gz,&len);
430: if (len == 3) {
431: *gz = 0;
432: }
433: }
434:
435: PetscStrcat(infoname,".info");
436: PetscFixFilename(infoname,iname);
437: if (type == PETSC_BINARY_RDONLY) {
438: PetscFileRetrieve(viewer->comm,iname,infoname,256,&found);
439: if (found) {
440: vbinary->fdes_info = fopen(infoname,"r");
441: if (vbinary->fdes_info) {
442: PetscViewerBinaryLoadInfo(viewer);
443: fclose(vbinary->fdes_info);
444: }
445: vbinary->fdes_info = fopen(infoname,"r");
446: }
447: } else if (!vbinary->skipinfo) {
448: vbinary->fdes_info = fopen(infoname,"w");
449: if (!vbinary->fdes_info) {
450: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
451: }
452: }
453: }
455: #if defined(PETSC_USE_LOG)
456: PetscLogObjectState((PetscObject)viewer,"File: %s",name);
457: #endif
458: return(0);
459: }
460: EXTERN_C_END
462: EXTERN_C_BEGIN
463: int PetscViewerCreate_Binary(PetscViewer v)
464: {
465: int ierr;
466: PetscViewer_Binary *vbinary;
469: ierr = PetscNew(PetscViewer_Binary,&vbinary);
470: v->data = (void*)vbinary;
471: v->ops->destroy = PetscViewerDestroy_Binary;
472: v->ops->flush = 0;
473: v->iformat = 0;
474: vbinary->fdes_info = 0;
475: vbinary->fdes = 0;
476: vbinary->skipinfo = PETSC_FALSE;
477: v->ops->getsingleton = PetscViewerGetSingleton_Binary;
478: v->ops->restoresingleton = PetscViewerRestoreSingleton_Binary;
479: vbinary->btype = (PetscViewerBinaryType) -1;
480: vbinary->storecompressed = PETSC_FALSE;
481: vbinary->filename = 0;
483: PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerSetFilename_C",
484: "PetscViewerSetFilename_Binary",
485: PetscViewerSetFilename_Binary);
486: PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerBinarySetType_C",
487: "PetscViewerBinarySetType_Binary",
488: PetscViewerBinarySetType_Binary);
489: return(0);
490: }
491: EXTERN_C_END
494: /* ---------------------------------------------------------------------*/
495: /*
496: The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
497: is attached to a communicator, in this case the attribute is a PetscViewer.
498: */
499: static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
501: /*@C
502: PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
503: in a communicator.
505: Collective on MPI_Comm
507: Input Parameter:
508: . comm - the MPI communicator to share the binary PetscViewer
509:
510: Level: intermediate
512: Options Database Keys:
513: $ -viewer_BINARY_filename <name>
515: Environmental variables:
516: - PETSC_VIEWER_BINARY_FILENAME
518: Notes:
519: Unlike almost all other PETSc routines, PETSC_VIEWER_BINARY_ does not return
520: an error code. The binary PetscViewer is usually used in the form
521: $ XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));
523: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
524: PetscViewerDestroy()
525: @*/
526: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
527: {
528: int ierr;
529: PetscTruth flg;
530: PetscViewer viewer;
531: char fname[256];
534: if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
535: MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
536: if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
537: }
538: MPI_Attr_get(comm,Petsc_Viewer_Binary_keyval,(void **)&viewer,(int *)&flg);
539: if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
540: if (!flg) { /* PetscViewer not yet created */
541: PetscOptionsGetenv(comm,"PETSC_VIEWER_BINARY_FILENAME",fname,256,&flg);
542: if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
543: if (!flg) {
544: PetscStrcpy(fname,"binaryoutput");
545: if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
546: }
547: PetscViewerBinaryOpen(comm,fname,PETSC_BINARY_CREATE,&viewer);
548: if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
549: PetscObjectRegisterDestroy((PetscObject)viewer);
550: if (ierr) {PetscError(__LINE__,"VIEWER_STDOUT_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
551: MPI_Attr_put(comm,Petsc_Viewer_Binary_keyval,(void*)viewer);
552: if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
553: }
554: PetscFunctionReturn(viewer);
555: }