xref: /petsc/src/sys/fileio/mpiuopen.c (revision f23aa3dd738493dcb3a70a8c0c7f5454aa9150c2)
1783b601eSJed Brown #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for popen */
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay       Some PETSc utilites routines to add simple parallel IO capability
4e5c89e4eSSatish Balay */
5c6db04a5SJed Brown #include <petscsys.h>
6e5c89e4eSSatish Balay #include <stdarg.h>
7e5c89e4eSSatish Balay #if defined(PETSC_HAVE_STDLIB_H)
8e5c89e4eSSatish Balay #include <stdlib.h>
9e5c89e4eSSatish Balay #endif
10e5c89e4eSSatish Balay 
11e5c89e4eSSatish Balay #undef __FUNCT__
12e5c89e4eSSatish Balay #define __FUNCT__ "PetscFOpen"
13e5c89e4eSSatish Balay /*@C
14e5c89e4eSSatish Balay     PetscFOpen - Has the first process in the communicator open a file;
15e5c89e4eSSatish Balay     all others do nothing.
16e5c89e4eSSatish Balay 
173f9fe445SBarry Smith     Logically Collective on MPI_Comm
18e5c89e4eSSatish Balay 
19e5c89e4eSSatish Balay     Input Parameters:
20e5c89e4eSSatish Balay +   comm - the communicator
21e5c89e4eSSatish Balay .   name - the filename
22e5c89e4eSSatish Balay -   mode - the mode for fopen(), usually "w"
23e5c89e4eSSatish Balay 
24e5c89e4eSSatish Balay     Output Parameter:
25e5c89e4eSSatish Balay .   fp - the file pointer
26e5c89e4eSSatish Balay 
27e5c89e4eSSatish Balay     Level: developer
28e5c89e4eSSatish Balay 
29e5c89e4eSSatish Balay     Notes:
30e5c89e4eSSatish Balay        PETSC_NULL (0), "stderr" or "stdout" may be passed in as the filename
31e5c89e4eSSatish Balay 
32e5c89e4eSSatish Balay     Fortran Note:
33e5c89e4eSSatish Balay     This routine is not supported in Fortran.
34e5c89e4eSSatish Balay 
35e5c89e4eSSatish Balay     Concepts: opening ASCII file
36e5c89e4eSSatish Balay     Concepts: files^opening ASCII
37e5c89e4eSSatish Balay 
38d75a2efbSBarry Smith .seealso: PetscFClose(), PetscSynchronizedFGets(), PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
39d75a2efbSBarry Smith           PetscFPrintf()
40e5c89e4eSSatish Balay @*/
417087cfbeSBarry Smith PetscErrorCode  PetscFOpen(MPI_Comm comm,const char name[],const char mode[],FILE **fp)
42e5c89e4eSSatish Balay {
43e5c89e4eSSatish Balay   PetscErrorCode ierr;
44e5c89e4eSSatish Balay   PetscMPIInt    rank;
45e5c89e4eSSatish Balay   FILE           *fd;
46e5c89e4eSSatish Balay   char           fname[PETSC_MAX_PATH_LEN],tname[PETSC_MAX_PATH_LEN];
47e5c89e4eSSatish Balay 
48e5c89e4eSSatish Balay   PetscFunctionBegin;
49e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
50e5c89e4eSSatish Balay   if (!rank) {
51ace3abfcSBarry Smith     PetscBool  isstdout,isstderr;
52e5c89e4eSSatish Balay     ierr = PetscStrcmp(name,"stdout",&isstdout);CHKERRQ(ierr);
53e5c89e4eSSatish Balay     ierr = PetscStrcmp(name,"stderr",&isstderr);CHKERRQ(ierr);
54e5c89e4eSSatish Balay     if (isstdout || !name) {
55da9f1d6bSBarry Smith       fd = PETSC_STDOUT;
56e5c89e4eSSatish Balay     } else if (isstderr) {
57da9f1d6bSBarry Smith       fd = PETSC_STDERR;
58e5c89e4eSSatish Balay     } else {
59e5c89e4eSSatish Balay       ierr = PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
60e5c89e4eSSatish Balay       ierr = PetscFixFilename(tname,fname);CHKERRQ(ierr);
61ae15b995SBarry Smith       ierr = PetscInfo1(0,"Opening file %s\n",fname);CHKERRQ(ierr);
62e5c89e4eSSatish Balay       fd   = fopen(fname,mode);
63e32f2f54SBarry Smith       if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file %s\n",fname);
64e5c89e4eSSatish Balay     }
65e5c89e4eSSatish Balay   } else fd = 0;
66e5c89e4eSSatish Balay   *fp = fd;
67e5c89e4eSSatish Balay   PetscFunctionReturn(0);
68e5c89e4eSSatish Balay }
69e5c89e4eSSatish Balay 
70e5c89e4eSSatish Balay #undef __FUNCT__
71e5c89e4eSSatish Balay #define __FUNCT__ "PetscFClose"
72e30d2299SSatish Balay /*@
73e5c89e4eSSatish Balay     PetscFClose - Has the first processor in the communicator close a
74e5c89e4eSSatish Balay     file; all others do nothing.
75e5c89e4eSSatish Balay 
763f9fe445SBarry Smith     Logically Collective on MPI_Comm
77e5c89e4eSSatish Balay 
78e5c89e4eSSatish Balay     Input Parameters:
79e5c89e4eSSatish Balay +   comm - the communicator
80e5c89e4eSSatish Balay -   fd - the file, opened with PetscFOpen()
81e5c89e4eSSatish Balay 
82e5c89e4eSSatish Balay    Level: developer
83e5c89e4eSSatish Balay 
84e5c89e4eSSatish Balay     Fortran Note:
85e5c89e4eSSatish Balay     This routine is not supported in Fortran.
86e5c89e4eSSatish Balay 
87e5c89e4eSSatish Balay     Concepts: files^closing ASCII
88e5c89e4eSSatish Balay     Concepts: closing file
89e5c89e4eSSatish Balay 
90e5c89e4eSSatish Balay .seealso: PetscFOpen()
91e5c89e4eSSatish Balay @*/
927087cfbeSBarry Smith PetscErrorCode  PetscFClose(MPI_Comm comm,FILE *fd)
93e5c89e4eSSatish Balay {
94e5c89e4eSSatish Balay   PetscErrorCode ierr;
95e5c89e4eSSatish Balay   PetscMPIInt    rank;
96ed9cf6e9SBarry Smith   int            err;
97e5c89e4eSSatish Balay 
98e5c89e4eSSatish Balay   PetscFunctionBegin;
99e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
100ed9cf6e9SBarry Smith   if (!rank && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
101ed9cf6e9SBarry Smith     err = fclose(fd);
102e32f2f54SBarry Smith     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
103ed9cf6e9SBarry Smith   }
104e5c89e4eSSatish Balay   PetscFunctionReturn(0);
105e5c89e4eSSatish Balay }
106e5c89e4eSSatish Balay 
107e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN)
108e5c89e4eSSatish Balay 
109e5c89e4eSSatish Balay #undef __FUNCT__
110e5c89e4eSSatish Balay #define __FUNCT__ "PetscPClose"
111e5c89e4eSSatish Balay /*@C
112e5c89e4eSSatish Balay       PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()
113e5c89e4eSSatish Balay 
114e5c89e4eSSatish Balay      Collective on MPI_Comm, but only process 0 runs the command
115e5c89e4eSSatish Balay 
116e5c89e4eSSatish Balay    Input Parameters:
117e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
118e5c89e4eSSatish Balay -   fp - the file pointer where program input or output may be read or PETSC_NULL if don't care
119e5c89e4eSSatish Balay 
120784ad74dSJed Brown    Output Parameters:
121784ad74dSJed Brown .   rval - return value from pclose() or PETSC_NULL to raise an error on failure
122784ad74dSJed Brown 
123e5c89e4eSSatish Balay    Level: intermediate
124e5c89e4eSSatish Balay 
125e5c89e4eSSatish Balay    Notes:
126e5c89e4eSSatish Balay        Does not work under Windows
127e5c89e4eSSatish Balay 
128e5c89e4eSSatish Balay .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()
129e5c89e4eSSatish Balay 
130e5c89e4eSSatish Balay @*/
131784ad74dSJed Brown PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd,PetscInt *rval)
132e5c89e4eSSatish Balay {
133e5c89e4eSSatish Balay   PetscErrorCode ierr;
134e5c89e4eSSatish Balay   PetscMPIInt    rank;
135ed9cf6e9SBarry Smith   int            err;
136e5c89e4eSSatish Balay 
137e5c89e4eSSatish Balay   PetscFunctionBegin;
138e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
139e5c89e4eSSatish Balay   if (!rank) {
140e5c89e4eSSatish Balay     char buf[1024];
141e5c89e4eSSatish Balay     while (fgets(buf,1024,fd)) {;} /* wait till it prints everything */
142ed9cf6e9SBarry Smith     err = pclose(fd);
143784ad74dSJed Brown     if (rval) *rval = err;
144784ad74dSJed Brown     else if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"pclose() failed with error code %D",err);
145e5c89e4eSSatish Balay   }
146e5c89e4eSSatish Balay   PetscFunctionReturn(0);
147e5c89e4eSSatish Balay }
148e5c89e4eSSatish Balay 
149e5c89e4eSSatish Balay 
150e5c89e4eSSatish Balay #undef __FUNCT__
151e5c89e4eSSatish Balay #define __FUNCT__ "PetscPOpen"
152e5c89e4eSSatish Balay /*@C
153e5c89e4eSSatish Balay       PetscPOpen - Runs a program on processor zero and sends either its input or output to
154e5c89e4eSSatish Balay           a file.
155e5c89e4eSSatish Balay 
1563f9fe445SBarry Smith      Logically Collective on MPI_Comm, but only process 0 runs the command
157e5c89e4eSSatish Balay 
158e5c89e4eSSatish Balay    Input Parameters:
159e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
160e5c89e4eSSatish Balay .   machine - machine to run command on or PETSC_NULL, or string with 0 in first location
161e5c89e4eSSatish Balay .   program - name of program to run
162e5c89e4eSSatish Balay -   mode - either r or w
163e5c89e4eSSatish Balay 
164e5c89e4eSSatish Balay    Output Parameter:
165e5c89e4eSSatish Balay .   fp - the file pointer where program input or output may be read or PETSC_NULL if don't care
166e5c89e4eSSatish Balay 
167e5c89e4eSSatish Balay    Level: intermediate
168e5c89e4eSSatish Balay 
169e5c89e4eSSatish Balay    Notes:
170e5c89e4eSSatish Balay        Use PetscPClose() to close the file pointer when you are finished with it
171e5c89e4eSSatish Balay        Does not work under Windows
172e5c89e4eSSatish Balay 
173e5c89e4eSSatish Balay        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
174e5c89e4eSSatish Balay     will be replaced with relevent values.
175e5c89e4eSSatish Balay 
176e5c89e4eSSatish Balay .seealso: PetscFOpen(), PetscFClose(), PetscPClose()
177e5c89e4eSSatish Balay 
178e5c89e4eSSatish Balay @*/
1797087cfbeSBarry Smith PetscErrorCode  PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
180e5c89e4eSSatish Balay {
181e5c89e4eSSatish Balay   PetscErrorCode ierr;
182e5c89e4eSSatish Balay   PetscMPIInt    rank;
183e5c89e4eSSatish Balay   size_t         i,len,cnt;
184e5c89e4eSSatish Balay   char           commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
185e5c89e4eSSatish Balay   FILE           *fd;
186e5c89e4eSSatish Balay 
187e5c89e4eSSatish Balay   PetscFunctionBegin;
188e5c89e4eSSatish Balay   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
189e5c89e4eSSatish Balay   if (machine && machine[0]) {
190e5c89e4eSSatish Balay     ierr = PetscStrcpy(command,"ssh ");CHKERRQ(ierr);
191e5c89e4eSSatish Balay     ierr = PetscStrcat(command,machine);CHKERRQ(ierr);
192d5649816SBarry Smith     ierr = PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");CHKERRQ(ierr);
193e5c89e4eSSatish Balay     /*
194e5c89e4eSSatish Balay         Copy program into command but protect the " with a \ in front of it
195e5c89e4eSSatish Balay     */
196e5c89e4eSSatish Balay     ierr = PetscStrlen(command,&cnt);CHKERRQ(ierr);
197e5c89e4eSSatish Balay     ierr = PetscStrlen(program,&len);CHKERRQ(ierr);
198e5c89e4eSSatish Balay     for (i=0; i<len; i++) {
199e5c89e4eSSatish Balay       if (program[i] == '\"') {
200e5c89e4eSSatish Balay         command[cnt++] = '\\';
201e5c89e4eSSatish Balay       }
202e5c89e4eSSatish Balay       command[cnt++] = program[i];
203e5c89e4eSSatish Balay     }
204e5c89e4eSSatish Balay     command[cnt] = 0;
205e5c89e4eSSatish Balay     ierr = PetscStrcat(command,"\"");CHKERRQ(ierr);
206e5c89e4eSSatish Balay   } else {
207e5c89e4eSSatish Balay     ierr = PetscStrcpy(command,program);CHKERRQ(ierr);
208e5c89e4eSSatish Balay   }
209e5c89e4eSSatish Balay 
210e5c89e4eSSatish Balay   ierr = PetscStrreplace(comm,command,commandt,1024);CHKERRQ(ierr);
211e5c89e4eSSatish Balay 
212e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
213e5c89e4eSSatish Balay   if (!rank) {
214ae15b995SBarry Smith     ierr = PetscInfo1(0,"Running command :%s\n",commandt);CHKERRQ(ierr);
215*f23aa3ddSBarry Smith     if (!(fd = popen(commandt,mode))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot run command %s",commandt);
216e5c89e4eSSatish Balay     if (fp) *fp = fd;
217e5c89e4eSSatish Balay   }
218e5c89e4eSSatish Balay   PetscFunctionReturn(0);
219e5c89e4eSSatish Balay }
220e5c89e4eSSatish Balay 
221e5c89e4eSSatish Balay #endif
222