xref: /petsc/src/sys/fileio/mpiuopen.c (revision 0298fd7132830bec7daee99a80be0eddb2b310a5)
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:
30*0298fd71SBarry Smith        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);
54a297a907SKarl Rupp     if (isstdout || !name) fd = PETSC_STDOUT;
55a297a907SKarl Rupp     else if (isstderr) fd = PETSC_STDERR;
56a297a907SKarl Rupp     else {
57e5c89e4eSSatish Balay       ierr = PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
58e5c89e4eSSatish Balay       ierr = PetscFixFilename(tname,fname);CHKERRQ(ierr);
59ae15b995SBarry Smith       ierr = PetscInfo1(0,"Opening file %s\n",fname);CHKERRQ(ierr);
60e5c89e4eSSatish Balay       fd   = fopen(fname,mode);
61e32f2f54SBarry Smith       if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file %s\n",fname);
62e5c89e4eSSatish Balay     }
63e5c89e4eSSatish Balay   } else fd = 0;
64e5c89e4eSSatish Balay   *fp = fd;
65e5c89e4eSSatish Balay   PetscFunctionReturn(0);
66e5c89e4eSSatish Balay }
67e5c89e4eSSatish Balay 
68e5c89e4eSSatish Balay #undef __FUNCT__
69e5c89e4eSSatish Balay #define __FUNCT__ "PetscFClose"
70e30d2299SSatish Balay /*@
71e5c89e4eSSatish Balay     PetscFClose - Has the first processor in the communicator close a
72e5c89e4eSSatish Balay     file; all others do nothing.
73e5c89e4eSSatish Balay 
743f9fe445SBarry Smith     Logically Collective on MPI_Comm
75e5c89e4eSSatish Balay 
76e5c89e4eSSatish Balay     Input Parameters:
77e5c89e4eSSatish Balay +   comm - the communicator
78e5c89e4eSSatish Balay -   fd - the file, opened with PetscFOpen()
79e5c89e4eSSatish Balay 
80e5c89e4eSSatish Balay    Level: developer
81e5c89e4eSSatish Balay 
82e5c89e4eSSatish Balay     Fortran Note:
83e5c89e4eSSatish Balay     This routine is not supported in Fortran.
84e5c89e4eSSatish Balay 
85e5c89e4eSSatish Balay     Concepts: files^closing ASCII
86e5c89e4eSSatish Balay     Concepts: closing file
87e5c89e4eSSatish Balay 
88e5c89e4eSSatish Balay .seealso: PetscFOpen()
89e5c89e4eSSatish Balay @*/
907087cfbeSBarry Smith PetscErrorCode  PetscFClose(MPI_Comm comm,FILE *fd)
91e5c89e4eSSatish Balay {
92e5c89e4eSSatish Balay   PetscErrorCode ierr;
93e5c89e4eSSatish Balay   PetscMPIInt    rank;
94ed9cf6e9SBarry Smith   int            err;
95e5c89e4eSSatish Balay 
96e5c89e4eSSatish Balay   PetscFunctionBegin;
97e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
98ed9cf6e9SBarry Smith   if (!rank && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
99ed9cf6e9SBarry Smith     err = fclose(fd);
100e32f2f54SBarry Smith     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
101ed9cf6e9SBarry Smith   }
102e5c89e4eSSatish Balay   PetscFunctionReturn(0);
103e5c89e4eSSatish Balay }
104e5c89e4eSSatish Balay 
105e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN)
106e5c89e4eSSatish Balay 
107e5c89e4eSSatish Balay #undef __FUNCT__
108e5c89e4eSSatish Balay #define __FUNCT__ "PetscPClose"
109e5c89e4eSSatish Balay /*@C
110e5c89e4eSSatish Balay       PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()
111e5c89e4eSSatish Balay 
112e5c89e4eSSatish Balay      Collective on MPI_Comm, but only process 0 runs the command
113e5c89e4eSSatish Balay 
114e5c89e4eSSatish Balay    Input Parameters:
115e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
116*0298fd71SBarry Smith -   fp - the file pointer where program input or output may be read or NULL if don't care
117e5c89e4eSSatish Balay 
118784ad74dSJed Brown    Output Parameters:
119*0298fd71SBarry Smith .   rval - return value from pclose() or NULL to raise an error on failure
120784ad74dSJed Brown 
121e5c89e4eSSatish Balay    Level: intermediate
122e5c89e4eSSatish Balay 
123e5c89e4eSSatish Balay    Notes:
124e5c89e4eSSatish Balay        Does not work under Windows
125e5c89e4eSSatish Balay 
126e5c89e4eSSatish Balay .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()
127e5c89e4eSSatish Balay 
128e5c89e4eSSatish Balay @*/
129784ad74dSJed Brown PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd,PetscInt *rval)
130e5c89e4eSSatish Balay {
131e5c89e4eSSatish Balay   PetscErrorCode ierr;
132e5c89e4eSSatish Balay   PetscMPIInt    rank;
133ed9cf6e9SBarry Smith   int            err;
134e5c89e4eSSatish Balay 
135e5c89e4eSSatish Balay   PetscFunctionBegin;
136e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
137e5c89e4eSSatish Balay   if (!rank) {
138e5c89e4eSSatish Balay     char buf[1024];
139a297a907SKarl Rupp     while (fgets(buf,1024,fd)) ; /* wait till it prints everything */
140ed9cf6e9SBarry Smith     err = pclose(fd);
141784ad74dSJed Brown     if (rval) *rval = err;
142784ad74dSJed Brown     else if (err) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"pclose() failed with error code %D",err);
143e5c89e4eSSatish Balay   }
144e5c89e4eSSatish Balay   PetscFunctionReturn(0);
145e5c89e4eSSatish Balay }
146e5c89e4eSSatish Balay 
147e5c89e4eSSatish Balay 
148e5c89e4eSSatish Balay #undef __FUNCT__
149e5c89e4eSSatish Balay #define __FUNCT__ "PetscPOpen"
150e5c89e4eSSatish Balay /*@C
151e5c89e4eSSatish Balay       PetscPOpen - Runs a program on processor zero and sends either its input or output to
152e5c89e4eSSatish Balay           a file.
153e5c89e4eSSatish Balay 
1543f9fe445SBarry Smith      Logically Collective on MPI_Comm, but only process 0 runs the command
155e5c89e4eSSatish Balay 
156e5c89e4eSSatish Balay    Input Parameters:
157e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
158*0298fd71SBarry Smith .   machine - machine to run command on or NULL, or string with 0 in first location
159e5c89e4eSSatish Balay .   program - name of program to run
160e5c89e4eSSatish Balay -   mode - either r or w
161e5c89e4eSSatish Balay 
162e5c89e4eSSatish Balay    Output Parameter:
163*0298fd71SBarry Smith .   fp - the file pointer where program input or output may be read or NULL if don't care
164e5c89e4eSSatish Balay 
165e5c89e4eSSatish Balay    Level: intermediate
166e5c89e4eSSatish Balay 
167e5c89e4eSSatish Balay    Notes:
168e5c89e4eSSatish Balay        Use PetscPClose() to close the file pointer when you are finished with it
169e5c89e4eSSatish Balay        Does not work under Windows
170e5c89e4eSSatish Balay 
171e5c89e4eSSatish Balay        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
172e5c89e4eSSatish Balay     will be replaced with relevent values.
173e5c89e4eSSatish Balay 
174e5c89e4eSSatish Balay .seealso: PetscFOpen(), PetscFClose(), PetscPClose()
175e5c89e4eSSatish Balay 
176e5c89e4eSSatish Balay @*/
1777087cfbeSBarry Smith PetscErrorCode  PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
178e5c89e4eSSatish Balay {
179e5c89e4eSSatish Balay   PetscErrorCode ierr;
180e5c89e4eSSatish Balay   PetscMPIInt    rank;
181e5c89e4eSSatish Balay   size_t         i,len,cnt;
182e5c89e4eSSatish Balay   char           commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
183e5c89e4eSSatish Balay   FILE           *fd;
184e5c89e4eSSatish Balay 
185e5c89e4eSSatish Balay   PetscFunctionBegin;
186e5c89e4eSSatish Balay   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
187e5c89e4eSSatish Balay   if (machine && machine[0]) {
188e5c89e4eSSatish Balay     ierr = PetscStrcpy(command,"ssh ");CHKERRQ(ierr);
189e5c89e4eSSatish Balay     ierr = PetscStrcat(command,machine);CHKERRQ(ierr);
190d5649816SBarry Smith     ierr = PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");CHKERRQ(ierr);
191e5c89e4eSSatish Balay     /*
192e5c89e4eSSatish Balay         Copy program into command but protect the " with a \ in front of it
193e5c89e4eSSatish Balay     */
194e5c89e4eSSatish Balay     ierr = PetscStrlen(command,&cnt);CHKERRQ(ierr);
195e5c89e4eSSatish Balay     ierr = PetscStrlen(program,&len);CHKERRQ(ierr);
196e5c89e4eSSatish Balay     for (i=0; i<len; i++) {
197a297a907SKarl Rupp       if (program[i] == '\"') command[cnt++] = '\\';
198e5c89e4eSSatish Balay       command[cnt++] = program[i];
199e5c89e4eSSatish Balay     }
200e5c89e4eSSatish Balay     command[cnt] = 0;
201a297a907SKarl Rupp 
202e5c89e4eSSatish Balay     ierr = PetscStrcat(command,"\"");CHKERRQ(ierr);
203e5c89e4eSSatish Balay   } else {
204e5c89e4eSSatish Balay     ierr = PetscStrcpy(command,program);CHKERRQ(ierr);
205e5c89e4eSSatish Balay   }
206e5c89e4eSSatish Balay 
207e5c89e4eSSatish Balay   ierr = PetscStrreplace(comm,command,commandt,1024);CHKERRQ(ierr);
208e5c89e4eSSatish Balay 
209e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
210e5c89e4eSSatish Balay   if (!rank) {
211ae15b995SBarry Smith     ierr = PetscInfo1(0,"Running command :%s\n",commandt);CHKERRQ(ierr);
212f23aa3ddSBarry Smith     if (!(fd = popen(commandt,mode))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot run command %s",commandt);
213e5c89e4eSSatish Balay     if (fp) *fp = fd;
214e5c89e4eSSatish Balay   }
215e5c89e4eSSatish Balay   PetscFunctionReturn(0);
216e5c89e4eSSatish Balay }
217e5c89e4eSSatish Balay 
218e5c89e4eSSatish Balay #endif
219