Actual source code: binv.c
1: /*$Id: binv.c,v 1.99 2001/04/10 19:34:06 bsmith Exp $*/
3: #include petscsys.h
4: #include src/sys/src/viewer/viewerimpl.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: } PetscViewer_Binary;
21: int PetscViewerGetSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
22: {
23: int rank,ierr;
24: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data,*obinary;
27: MPI_Comm_rank(viewer->comm,&rank);
28: if (!rank) {
29: ierr = PetscViewerCreate(PETSC_COMM_SELF,outviewer);
30: ierr = PetscViewerSetType(*outviewer,PETSC_VIEWER_BINARY);
31: obinary = (PetscViewer_Binary*)(*outviewer)->data;
32: ierr = PetscMemcpy(obinary,vbinary,sizeof(PetscViewer_Binary));
33: } else {
34: *outviewer = 0;
35: }
36: return(0);
37: }
39: int PetscViewerRestoreSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
40: {
41: int ierr,rank;
44: MPI_Comm_rank(viewer->comm,&rank);
45: if (!rank) {
46: PetscFree((*outviewer)->data);
47: PetscLogObjectDestroy((PetscObject)*outviewer);
48: PetscHeaderDestroy((PetscObject)*outviewer);
49: }
50: return(0);
51: }
53: /*@C
54: PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.
56: Not Collective
58: + viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
59: - fdes - file descriptor
61: Level: advanced
63: Notes:
64: For writable binary PetscViewers, the descriptor will only be valid for the
65: first processor in the communicator that shares the PetscViewer. For readable
66: files it will only be valid on nodes that have the file. If node 0 does not
67: have the file it generates an error even if another node does have the file.
68:
69: Fortran Note:
70: This routine is not supported in Fortran.
72: Concepts: file descriptor^getting
73: Concepts: PetscViewerBinary^accessing file descriptor
75: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
76: @*/
77: int PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
78: {
79: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
82: *fdes = vbinary->fdes;
83: return(0);
84: }
86: /*@C
87: PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
88: info file associated with a binary file.
90: Not Collective
92: + viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
93: - file - file pointer
95: Level: advanced
97: Notes:
98: For writable binary PetscViewers, the descriptor will only be valid for the
99: first processor in the communicator that shares the PetscViewer.
100:
101: Fortran Note:
102: This routine is not supported in Fortran.
104: Concepts: PetscViewerBinary^accessing info file
106: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
107: @*/
108: int PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
109: {
110: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
113: *file = vbinary->fdes_info;
114: return(0);
115: }
117: int PetscViewerDestroy_Binary(PetscViewer v)
118: {
119: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
120: int ierr,rank;
123: MPI_Comm_rank(v->comm,&rank);
124: if (!rank && vbinary->fdes) {
125: close(vbinary->fdes);
126: if (vbinary->storecompressed) {
127: char par[1024],buf[1024];
128: FILE *fp;
129: /* compress the file */
130: PetscStrcpy(par,"gzip ");
131: PetscStrcat(par,vbinary->filename);
132: PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,par,"r",&fp);
133: if (fgets(buf,1024,fp)) {
134: SETERRQ2(1,"Error from command %sn%s",par,buf);
135: }
136: PetscPClose(PETSC_COMM_SELF,fp);
137: }
138: }
139: if (vbinary->fdes_info) fclose(vbinary->fdes_info);
140: PetscStrfree(vbinary->filename);
141: PetscFree(vbinary);
142: return(0);
143: }
145: /*@C
146: PetscViewerBinaryOpen - Opens a file for binary input/output.
148: Collective on MPI_Comm
150: Input Parameters:
151: + comm - MPI communicator
152: . name - name of file
153: - type - type of file
154: $ PETSC_BINARY_CREATE - create new file for binary output
155: $ PETSC_BINARY_RDONLY - open existing file for binary input
156: $ PETSC_BINARY_WRONLY - open existing file for binary output
158: Output Parameter:
159: . binv - PetscViewer for binary input/output to use with the specified file
161: Level: beginner
163: Note:
164: This PetscViewer should be destroyed with PetscViewerDestroy().
166: For reading files, the filename may begin with ftp:// or http:// and/or
167: end with .gz; in this case file is brought over and uncompressed.
169: For creating files, if the file name ends with .gz it is automatically
170: compressed when closed.
172: For writing files it only opens the file on processor 0 in the communicator.
173: For readable files it opens the file on all nodes that have the file. If
174: node 0 does not have the file it generates an error even if other nodes
175: do have the file.
177: Concepts: binary files
178: Concepts: PetscViewerBinary^creating
179: Concepts: gzip
180: Concepts: accessing remote file
181: Concepts: remote file
183: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
184: VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
185: PetscViewerBinaryGetInfoPointer()
186: @*/
187: int PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscViewerBinaryType type,PetscViewer *binv)
188: {
190:
192: PetscViewerCreate(comm,binv);
193: PetscViewerSetType(*binv,PETSC_VIEWER_BINARY);
194: PetscViewerBinarySetType(*binv,type);
195: PetscViewerSetFilename(*binv,name);
196: return(0);
197: }
199: /*@C
200: PetscViewerBinarySetType - Sets the type of binary file to be open
202: Collective on PetscViewer
204: Input Parameters:
205: + viewer - the PetscViewer; must be a binary PetscViewer
206: - type - type of file
207: $ PETSC_BINARY_CREATE - create new file for binary output
208: $ PETSC_BINARY_RDONLY - open existing file for binary input
209: $ PETSC_BINARY_WRONLY - open existing file for binary output
211: Level: advanced
213: .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
215: @*/
216: int PetscViewerBinarySetType(PetscViewer viewer,PetscViewerBinaryType type)
217: {
218: int ierr,(*f)(PetscViewer,PetscViewerBinaryType);
222: PetscObjectQueryFunction((PetscObject)viewer,"PetscViewerBinarySetType_C",(void (**)())&f);
223: if (f) {
224: (*f)(viewer,type);
225: }
227: return(0);
228: }
230: EXTERN_C_BEGIN
231: int PetscViewerBinarySetType_Binary(PetscViewer viewer,PetscViewerBinaryType type)
232: {
233: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
236: vbinary->btype = type;
237: return(0);
238: }
239: EXTERN_C_END
241: /*
242: PetscViewerBinaryLoadInfo options from the name.info file
243: if it exists.
244: */
245: int PetscViewerBinaryLoadInfo(PetscViewer viewer)
246: {
247: FILE *file;
248: char string[128],*first,*second,*final;
249: int len,ierr;
250: PetscTruth flg;
253: PetscOptionsHasName(PETSC_NULL,"-load_ignore_info",&flg);
254: if (flg) return(0);
256: PetscViewerBinaryGetInfoPointer(viewer,&file);
257: if (!file) return(0);
259: /* read rows of the file adding them to options database */
260: while (fgets(string,128,file)) {
261: /* Comments are indicated by #, ! or % in the first column */
262: if (string[0] == '#') continue;
263: if (string[0] == '!') continue;
264: if (string[0] == '%') continue;
265: PetscStrtok(string," ",&first);
266: PetscStrtok(0," ",&second);
267: if (first && first[0] == '-') {
268: PetscTruth wrongtype;
269: /*
270: Check for -mat_complex or -mat_double
271: */
272: #if defined(PETSC_USE_COMPLEX)
273: PetscStrncmp(first,"-mat_double",11,&wrongtype);
274: if (wrongtype) {
275: SETERRQ(1,"Loading double number matrix with complex number code");
276: }
277: #else
278: PetscStrncmp(first,"-mat_complex",12,&wrongtype);
279: if (wrongtype) {
280: SETERRQ(1,"Loading complex number matrix with double number code");
281: }
282: #endif
284: if (second) {final = second;} else {final = first;}
285: PetscStrlen(final,&len);
286: while (len > 0 && (final[len-1] == ' ' || final[len-1] == 'n')) {
287: len--; final[len] = 0;
288: }
289: PetscOptionsSetValue(first,second);
290: }
291: }
292: return(0);
294: }
296: /*
297: Actually opens the file
298: */
299: EXTERN_C_BEGIN
300: int PetscViewerSetFilename_Binary(PetscViewer viewer,const char name[])
301: {
302: int rank,ierr,len;
303: PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
304: const char *fname;
305: char bname[1024],*gz;
306: PetscTruth found;
307: PetscViewerBinaryType type = vbinary->btype;
310: if (type == (PetscViewerBinaryType) -1) {
311: SETERRQ(1,"Must call PetscViewerBinarySetType() before PetscViewerSetFilename()");
312: }
313: MPI_Comm_rank(viewer->comm,&rank);
315: /* copy name so we can edit it */
316: PetscStrallocpy(name,&vbinary->filename);
318: /* if ends in .gz strip that off and note user wants file compressed */
319: vbinary->storecompressed = PETSC_FALSE;
320: if (!rank && type == PETSC_BINARY_CREATE) {
321: /* remove .gz if it ends library name */
322: PetscStrstr(vbinary->filename,".gz",&gz);
323: if (gz) {
324: PetscStrlen(gz,&len);
325: if (len == 3) {
326: *gz = 0;
327: vbinary->storecompressed = PETSC_TRUE;
328: }
329: }
330: }
332: /* only first processor opens file if writeable */
333: if (!rank || type == PETSC_BINARY_RDONLY) {
335: if (type == PETSC_BINARY_RDONLY){
336: /* possibly get the file from remote site or compressed file */
337: ierr = PetscFileRetrieve(viewer->comm,vbinary->filename,bname,1024,&found);
338: fname = bname;
339: if (!rank && !found) {
340: SETERRQ1(1,"Cannot locate file: %s on node zero",vbinary->filename);
341: } else if (!found) {
342: PetscLogInfo(viewer,"Nonzero processor did not locate readonly file");
343: fname = 0;
344: }
345: } else {
346: fname = vbinary->filename;
347: }
349: #if defined(PARCH_win32_gnu) || defined(PARCH_win32)
350: if (type == PETSC_BINARY_CREATE) {
351: if ((vbinary->fdes = open(fname,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
352: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
353: }
354: } else if (type == PETSC_BINARY_RDONLY && fname) {
355: if ((vbinary->fdes = open(fname,O_RDONLY|O_BINARY,0)) == -1) {
356: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
357: }
358: } else if (type == PETSC_BINARY_WRONLY) {
359: if ((vbinary->fdes = open(fname,O_WRONLY|O_BINARY,0)) == -1) {
360: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
361: }
362: } else if (fname) {
363: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
364: }
365: #else
366: if (type == PETSC_BINARY_CREATE) {
367: if ((vbinary->fdes = creat(fname,0666)) == -1) {
368: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
369: }
370: } else if (type == PETSC_BINARY_RDONLY && fname) {
371: if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) {
372: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
373: }
374: } else if (type == PETSC_BINARY_WRONLY) {
375: if ((vbinary->fdes = open(fname,O_WRONLY,0)) == -1) {
376: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
377: }
378: } else if (fname) {
379: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
380: }
381: #endif
382: } else vbinary->fdes = -1;
383: viewer->format = PETSC_VIEWER_NOFORMAT;
385: /*
386: try to open info file: all processors open this file if read only
387: */
388: if (!rank || type == PETSC_BINARY_RDONLY) {
389: char infoname[256],iname[256];
390:
391: PetscStrcpy(infoname,name);
392: /* remove .gz if it ends library name */
393: PetscStrstr(infoname,".gz",&gz);
394: if (gz) {
395: PetscStrlen(gz,&len);
396: if (len == 3) {
397: *gz = 0;
398: }
399: }
400:
401: PetscStrcat(infoname,".info");
402: PetscFixFilename(infoname,iname);
403: if (type == PETSC_BINARY_RDONLY) {
404: PetscFileRetrieve(viewer->comm,iname,infoname,256,&found);
405: if (found) {
406: vbinary->fdes_info = fopen(infoname,"r");
407: if (vbinary->fdes_info) {
408: PetscViewerBinaryLoadInfo(viewer);
409: fclose(vbinary->fdes_info);
410: }
411: vbinary->fdes_info = fopen(infoname,"r");
412: }
413: } else {
414: vbinary->fdes_info = fopen(infoname,"w");
415: if (! vbinary->fdes_info) {
416: SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
417: }
418: }
419: }
421: #if defined(PETSC_USE_LOG)
422: PetscLogObjectState((PetscObject)viewer,"File: %s",name);
423: #endif
424: return(0);
425: }
426: EXTERN_C_END
428: EXTERN_C_BEGIN
429: int PetscViewerCreate_Binary(PetscViewer v)
430: {
431: int ierr;
432: PetscViewer_Binary *vbinary;
435: ierr = PetscNew(PetscViewer_Binary,&vbinary);
436: v->data = (void*)vbinary;
437: v->ops->destroy = PetscViewerDestroy_Binary;
438: v->ops->flush = 0;
439: v->iformat = 0;
440: vbinary->fdes_info = 0;
441: vbinary->fdes = 0;
442: v->ops->getsingleton = PetscViewerGetSingleton_Binary;
443: v->ops->restoresingleton = PetscViewerRestoreSingleton_Binary;
444: vbinary->btype = (PetscViewerBinaryType) -1;
445: vbinary->storecompressed = PETSC_FALSE;
446: vbinary->filename = 0;
448: PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerSetFilename_C",
449: "PetscViewerSetFilename_Binary",
450: PetscViewerSetFilename_Binary);
451: PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerBinarySetType_C",
452: "PetscViewerBinarySetType_Binary",
453: PetscViewerBinarySetType_Binary);
454: return(0);
455: }
456: EXTERN_C_END
459: /* ---------------------------------------------------------------------*/
460: /*
461: The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
462: is attached to a communicator, in this case the attribute is a PetscViewer.
463: */
464: static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
466: /*@C
467: PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
468: in a communicator.
470: Collective on MPI_Comm
472: Input Parameter:
473: . comm - the MPI communicator to share the binary PetscViewer
474:
475: Level: intermediate
477: Options Database Keys:
478: $ -viewer_BINARY_filename <name>
480: Environmental variables:
481: - PETSC_VIEWER_BINARY_FILENAME
483: Notes:
484: Unlike almost all other PETSc routines, PETSC_VIEWER_BINARY_ does not return
485: an error code. The binary PetscViewer is usually used in the form
486: $ XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));
488: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
489: PetscViewerDestroy()
490: @*/
491: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
492: {
493: int ierr;
494: PetscTruth flg;
495: PetscViewer viewer;
496: char fname[256];
499: if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
500: MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
501: if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
502: }
503: MPI_Attr_get(comm,Petsc_Viewer_Binary_keyval,(void **)&viewer,(int *)&flg);
504: if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
505: if (!flg) { /* PetscViewer not yet created */
506: PetscOptionsGetenv(comm,"PETSC_VIEWER_BINARY_FILENAME",fname,256,&flg);
507: if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
508: if (!flg) {
509: PetscStrcpy(fname,"binaryoutput");
510: if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
511: }
512: PetscViewerBinaryOpen(comm,fname,PETSC_BINARY_CREATE,&viewer);
513: if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
514: PetscObjectRegisterDestroy((PetscObject)viewer);
515: if (ierr) {PetscError(__LINE__,"VIEWER_STDOUT_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
516: MPI_Attr_put(comm,Petsc_Viewer_Binary_keyval,(void*)viewer);
517: if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
518: }
519: PetscFunctionReturn(viewer);
520: }