Actual source code: mpiuopen.c

  1: /*
  2:       Some PETSc utilites routines to add simple parallel IO capability
  3: */
 4:  #include petsc.h
 5:  #include petscsys.h
  6: #include <stdarg.h>
  7: #if defined(PETSC_HAVE_STDLIB_H)
  8: #include <stdlib.h>
  9: #endif
 10: #include "petscfix.h"

 14: /*@C
 15:     PetscFOpen - Has the first process in the communicator open a file;
 16:     all others do nothing.

 18:     Collective on MPI_Comm

 20:     Input Parameters:
 21: +   comm - the communicator
 22: .   name - the filename
 23: -   mode - the mode for fopen(), usually "w"

 25:     Output Parameter:
 26: .   fp - the file pointer

 28:     Level: developer

 30:     Notes:
 31:        PETSC_NULL (0), "stderr" or "stdout" may be passed in as the filename
 32:   
 33:     Fortran Note:
 34:     This routine is not supported in Fortran.

 36:     Concepts: opening ASCII file
 37:     Concepts: files^opening ASCII

 39: .seealso: PetscFClose()
 40: @*/
 41: PetscErrorCode PetscFOpen(MPI_Comm comm,const char name[],const char mode[],FILE **fp)
 42: {
 44:   int  rank;
 45:   FILE *fd;
 46:   char fname[PETSC_MAX_PATH_LEN],tname[PETSC_MAX_PATH_LEN];

 49:   MPI_Comm_rank(comm,&rank);
 50:   if (!rank) {
 51:     PetscTruth isstdout,isstderr;
 52:     PetscStrcmp(name,"stdout",&isstdout);
 53:     PetscStrcmp(name,"stderr",&isstderr);
 54:     if (isstdout || !name) {
 55:       fd = stdout;
 56:     } else if (isstderr) {
 57:       fd = stderr;
 58:     } else {
 59:       PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);
 60:       PetscFixFilename(tname,fname);
 61:       PetscLogInfo(0,"Opening file %s\n",fname);
 62:       fd   = fopen(fname,mode);
 63:       if (!fd) SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to open file %s\n",fname);
 64:     }
 65:   } else fd = 0;
 66:   *fp = fd;
 67:   return(0);
 68: }

 72: /*@C
 73:     PetscFClose - Has the first processor in the communicator close a 
 74:     file; all others do nothing.

 76:     Collective on MPI_Comm

 78:     Input Parameters:
 79: +   comm - the communicator
 80: -   fd - the file, opened with PetscFOpen()

 82:    Level: developer

 84:     Fortran Note:
 85:     This routine is not supported in Fortran.

 87:     Concepts: files^closing ASCII
 88:     Concepts: closing file

 90: .seealso: PetscFOpen()
 91: @*/
 92: PetscErrorCode PetscFClose(MPI_Comm comm,FILE *fd)
 93: {
 95:   int  rank;

 98:   MPI_Comm_rank(comm,&rank);
 99:   if (!rank && fd != stdout && fd != stderr) fclose(fd);
100:   return(0);
101: }

105: /*@C
106:       PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()

108:      Collective on MPI_Comm, but only process 0 runs the command

110:    Input Parameters:
111: +   comm - MPI communicator, only processor zero runs the program
112: -   fp - the file pointer where program input or output may be read or PETSC_NULL if don't care

114:    Level: intermediate

116:    Notes:
117:        Does not work under Windows

119: .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()

121: @*/
122: PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd)
123: {
125:   int  rank;

128:   MPI_Comm_rank(comm,&rank);
129:   if (!rank) {
130:     char buf[1024];
131:     while (fgets(buf,1024,fd)) {;} /* wait till it prints everything */
132: #if defined(PETSC_HAVE_POPEN)
133:     pclose(fd);
134: #else
135:     SETERRQ(PETSC_ERR_SUP_SYS,"Cannot run programs, no popen() on this computing system");
136: #endif
137:   }
138:   return(0);
139: }

143: /*@C
144:       PetscPOpen - Runs a program on processor zero and sends either its input or output to 
145:           a file.

147:      Collective on MPI_Comm, but only process 0 runs the command

149:    Input Parameters:
150: +   comm - MPI communicator, only processor zero runs the program
151: .   machine - machine to run command on or PETSC_NULL, or string with 0 in first location
152: .   program - name of program to run
153: -   mode - either r or w

155:    Output Parameter:
156: .   fp - the file pointer where program input or output may be read or PETSC_NULL if don't care

158:    Level: intermediate

160:    Notes:
161:        Does not work under Windows

163:        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
164:     will be replaced with relevent values.

166: .seealso: PetscFOpen(), PetscFClose(), PetscPClose()

168: @*/
169: PetscErrorCode PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
170: {
172:   int            rank;
173:   size_t         i,len,cnt;
174:   char           commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
175: #if defined(PETSC_HAVE_POPEN)
176:   FILE           *fd;
177: #endif


181:   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
182:   if (machine && machine[0]) {
183:     PetscStrcpy(command,"rsh ");
184:     PetscStrcat(command,machine);
185:     PetscStrcat(command," \" setenv DISPLAY ${DISPLAY}; ");
186:     /*
187:         Copy program into command but protect the " with a \ in front of it 
188:     */
189:     PetscStrlen(command,&cnt);
190:     PetscStrlen(program,&len);
191:     for (i=0; i<len; i++) {
192:       if (program[i] == '\"') {
193:         command[cnt++] = '\\';
194:       }
195:       command[cnt++] = program[i];
196:     }
197:     command[cnt] = 0;
198:     PetscStrcat(command,"\"");
199:   } else {
200:     PetscStrcpy(command,program);
201:   }

203:   PetscStrreplace(comm,command,commandt,1024);
204: 
205:   MPI_Comm_rank(comm,&rank);
206:   if (!rank) {
207:     PetscLogInfo(0,"Running command :%s\n",commandt);

209: #if defined(PETSC_HAVE_POPEN)
210:     if (!(fd = popen(commandt,mode))) {
211:        SETERRQ1(PETSC_ERR_LIB,"Cannot run command %s",commandt);
212:     }
213:     if (fp) *fp = fd;
214: #else 
215:     SETERRQ(PETSC_ERR_SUP_SYS,"Cannot run programs, no popen() on this system");
216: #endif
217:   }
218:   return(0);
219: }