xref: /petsc/src/sys/fileio/mpiuopen.c (revision 74ba86544df403e2c1569b1354fad84130cbc85d)
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 
7d0286d30SJed Brown #include <errno.h>
8d0286d30SJed Brown 
9e5c89e4eSSatish Balay #undef __FUNCT__
10e5c89e4eSSatish Balay #define __FUNCT__ "PetscFOpen"
11e5c89e4eSSatish Balay /*@C
12e5c89e4eSSatish Balay     PetscFOpen - Has the first process in the communicator open a file;
13e5c89e4eSSatish Balay     all others do nothing.
14e5c89e4eSSatish Balay 
153f9fe445SBarry Smith     Logically Collective on MPI_Comm
16e5c89e4eSSatish Balay 
17e5c89e4eSSatish Balay     Input Parameters:
18e5c89e4eSSatish Balay +   comm - the communicator
19e5c89e4eSSatish Balay .   name - the filename
20e5c89e4eSSatish Balay -   mode - the mode for fopen(), usually "w"
21e5c89e4eSSatish Balay 
22e5c89e4eSSatish Balay     Output Parameter:
23e5c89e4eSSatish Balay .   fp - the file pointer
24e5c89e4eSSatish Balay 
25e5c89e4eSSatish Balay     Level: developer
26e5c89e4eSSatish Balay 
27e5c89e4eSSatish Balay     Notes:
280298fd71SBarry Smith        NULL (0), "stderr" or "stdout" may be passed in as the filename
29e5c89e4eSSatish Balay 
30e5c89e4eSSatish Balay     Fortran Note:
31e5c89e4eSSatish Balay     This routine is not supported in Fortran.
32e5c89e4eSSatish Balay 
33e5c89e4eSSatish Balay     Concepts: opening ASCII file
34e5c89e4eSSatish Balay     Concepts: files^opening ASCII
35e5c89e4eSSatish Balay 
36d75a2efbSBarry Smith .seealso: PetscFClose(), PetscSynchronizedFGets(), PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
37d75a2efbSBarry Smith           PetscFPrintf()
38e5c89e4eSSatish Balay @*/
397087cfbeSBarry Smith PetscErrorCode  PetscFOpen(MPI_Comm comm,const char name[],const char mode[],FILE **fp)
40e5c89e4eSSatish Balay {
41e5c89e4eSSatish Balay   PetscErrorCode ierr;
42e5c89e4eSSatish Balay   PetscMPIInt    rank;
43e5c89e4eSSatish Balay   FILE           *fd;
44e5c89e4eSSatish Balay   char           fname[PETSC_MAX_PATH_LEN],tname[PETSC_MAX_PATH_LEN];
45e5c89e4eSSatish Balay 
46e5c89e4eSSatish Balay   PetscFunctionBegin;
47e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
48e5c89e4eSSatish Balay   if (!rank) {
49ace3abfcSBarry Smith     PetscBool isstdout,isstderr;
50e5c89e4eSSatish Balay     ierr = PetscStrcmp(name,"stdout",&isstdout);CHKERRQ(ierr);
51e5c89e4eSSatish Balay     ierr = PetscStrcmp(name,"stderr",&isstderr);CHKERRQ(ierr);
52a297a907SKarl Rupp     if (isstdout || !name) fd = PETSC_STDOUT;
53a297a907SKarl Rupp     else if (isstderr) fd = PETSC_STDERR;
54a297a907SKarl Rupp     else {
55e5c89e4eSSatish Balay       ierr = PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
56e5c89e4eSSatish Balay       ierr = PetscFixFilename(tname,fname);CHKERRQ(ierr);
57ae15b995SBarry Smith       ierr = PetscInfo1(0,"Opening file %s\n",fname);CHKERRQ(ierr);
58e5c89e4eSSatish Balay       fd   = fopen(fname,mode);
59e32f2f54SBarry Smith       if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file %s\n",fname);
60e5c89e4eSSatish Balay     }
61e5c89e4eSSatish Balay   } else fd = 0;
62e5c89e4eSSatish Balay   *fp = fd;
63e5c89e4eSSatish Balay   PetscFunctionReturn(0);
64e5c89e4eSSatish Balay }
65e5c89e4eSSatish Balay 
66e5c89e4eSSatish Balay #undef __FUNCT__
67e5c89e4eSSatish Balay #define __FUNCT__ "PetscFClose"
68e30d2299SSatish Balay /*@
69e5c89e4eSSatish Balay     PetscFClose - Has the first processor in the communicator close a
70e5c89e4eSSatish Balay     file; all others do nothing.
71e5c89e4eSSatish Balay 
723f9fe445SBarry Smith     Logically Collective on MPI_Comm
73e5c89e4eSSatish Balay 
74e5c89e4eSSatish Balay     Input Parameters:
75e5c89e4eSSatish Balay +   comm - the communicator
76e5c89e4eSSatish Balay -   fd - the file, opened with PetscFOpen()
77e5c89e4eSSatish Balay 
78e5c89e4eSSatish Balay    Level: developer
79e5c89e4eSSatish Balay 
80e5c89e4eSSatish Balay     Fortran Note:
81e5c89e4eSSatish Balay     This routine is not supported in Fortran.
82e5c89e4eSSatish Balay 
83e5c89e4eSSatish Balay     Concepts: files^closing ASCII
84e5c89e4eSSatish Balay     Concepts: closing file
85e5c89e4eSSatish Balay 
86e5c89e4eSSatish Balay .seealso: PetscFOpen()
87e5c89e4eSSatish Balay @*/
887087cfbeSBarry Smith PetscErrorCode  PetscFClose(MPI_Comm comm,FILE *fd)
89e5c89e4eSSatish Balay {
90e5c89e4eSSatish Balay   PetscErrorCode ierr;
91e5c89e4eSSatish Balay   PetscMPIInt    rank;
92ed9cf6e9SBarry Smith   int            err;
93e5c89e4eSSatish Balay 
94e5c89e4eSSatish Balay   PetscFunctionBegin;
95e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
96ed9cf6e9SBarry Smith   if (!rank && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
97ed9cf6e9SBarry Smith     err = fclose(fd);
98e32f2f54SBarry Smith     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
99ed9cf6e9SBarry Smith   }
100e5c89e4eSSatish Balay   PetscFunctionReturn(0);
101e5c89e4eSSatish Balay }
102e5c89e4eSSatish Balay 
103e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN)
104*74ba8654SBarry Smith static char PetscPOpenMachine[128] = "";
105e5c89e4eSSatish Balay 
106e5c89e4eSSatish Balay #undef __FUNCT__
107e5c89e4eSSatish Balay #define __FUNCT__ "PetscPClose"
108e5c89e4eSSatish Balay /*@C
109e5c89e4eSSatish Balay       PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()
110e5c89e4eSSatish Balay 
111e5c89e4eSSatish Balay      Collective on MPI_Comm, but only process 0 runs the command
112e5c89e4eSSatish Balay 
113e5c89e4eSSatish Balay    Input Parameters:
114e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1150298fd71SBarry Smith -   fp - the file pointer where program input or output may be read or NULL if don't care
116e5c89e4eSSatish Balay 
117784ad74dSJed Brown    Output Parameters:
1180298fd71SBarry Smith .   rval - return value from pclose() or NULL to raise an error on failure
119784ad74dSJed Brown 
120e5c89e4eSSatish Balay    Level: intermediate
121e5c89e4eSSatish Balay 
122e5c89e4eSSatish Balay    Notes:
123e5c89e4eSSatish Balay        Does not work under Windows
124e5c89e4eSSatish Balay 
125e5c89e4eSSatish Balay .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()
126e5c89e4eSSatish Balay 
127e5c89e4eSSatish Balay @*/
12896a8e8cbSBarry Smith PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd,int *rval)
129e5c89e4eSSatish Balay {
130e5c89e4eSSatish Balay   PetscErrorCode ierr;
131e5c89e4eSSatish Balay   PetscMPIInt    rank;
132ed9cf6e9SBarry Smith   int            err;
133e5c89e4eSSatish Balay 
134e5c89e4eSSatish Balay   PetscFunctionBegin;
135e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
136e5c89e4eSSatish Balay   if (!rank) {
137e5c89e4eSSatish Balay     char buf[1024];
138a297a907SKarl Rupp     while (fgets(buf,1024,fd)) ; /* wait till it prints everything */
139ed9cf6e9SBarry Smith     err = pclose(fd);
140784ad74dSJed Brown     if (rval) *rval = err;
141d0286d30SJed Brown     else if (err) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SYS,"pclose() failed with error code %d, errno %d",err,errno);
142e5c89e4eSSatish Balay   }
143e5c89e4eSSatish Balay   PetscFunctionReturn(0);
144e5c89e4eSSatish Balay }
145e5c89e4eSSatish Balay 
146e5c89e4eSSatish Balay 
147e5c89e4eSSatish Balay #undef __FUNCT__
148e5c89e4eSSatish Balay #define __FUNCT__ "PetscPOpen"
149e5c89e4eSSatish Balay /*@C
150e5c89e4eSSatish Balay       PetscPOpen - Runs a program on processor zero and sends either its input or output to
151e5c89e4eSSatish Balay           a file.
152e5c89e4eSSatish Balay 
1533f9fe445SBarry Smith      Logically Collective on MPI_Comm, but only process 0 runs the command
154e5c89e4eSSatish Balay 
155e5c89e4eSSatish Balay    Input Parameters:
156e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1570298fd71SBarry Smith .   machine - machine to run command on or NULL, or string with 0 in first location
158e5c89e4eSSatish Balay .   program - name of program to run
159e5c89e4eSSatish Balay -   mode - either r or w
160e5c89e4eSSatish Balay 
161e5c89e4eSSatish Balay    Output Parameter:
1620298fd71SBarry Smith .   fp - the file pointer where program input or output may be read or NULL if don't care
163e5c89e4eSSatish Balay 
164e5c89e4eSSatish Balay    Level: intermediate
165e5c89e4eSSatish Balay 
166e5c89e4eSSatish Balay    Notes:
167e5c89e4eSSatish Balay        Use PetscPClose() to close the file pointer when you are finished with it
168e5c89e4eSSatish Balay        Does not work under Windows
169e5c89e4eSSatish Balay 
170*74ba8654SBarry Smith        If machine is not provided will use the value set with PetsPOpenSetMachine() if that was provided, otherwise
171*74ba8654SBarry Smith        will use the machine running node zero of the communicator
172*74ba8654SBarry Smith 
173e5c89e4eSSatish Balay        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
174e5c89e4eSSatish Balay     will be replaced with relevent values.
175e5c89e4eSSatish Balay 
176*74ba8654SBarry Smith .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpenSetMachine()
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 */
189*74ba8654SBarry Smith   if (PetscPOpenMachine[0] || (machine && machine[0])) {
190e5c89e4eSSatish Balay     ierr = PetscStrcpy(command,"ssh ");CHKERRQ(ierr);
191*74ba8654SBarry Smith     if (PetscPOpenMachine[0]) {
192*74ba8654SBarry Smith       ierr = PetscStrcat(command,PetscPOpenMachine);CHKERRQ(ierr);
193*74ba8654SBarry Smith     } else {
194e5c89e4eSSatish Balay       ierr = PetscStrcat(command,machine);CHKERRQ(ierr);
195*74ba8654SBarry Smith     }
196d5649816SBarry Smith     ierr = PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");CHKERRQ(ierr);
197e5c89e4eSSatish Balay     /*
198e5c89e4eSSatish Balay         Copy program into command but protect the " with a \ in front of it
199e5c89e4eSSatish Balay     */
200e5c89e4eSSatish Balay     ierr = PetscStrlen(command,&cnt);CHKERRQ(ierr);
201e5c89e4eSSatish Balay     ierr = PetscStrlen(program,&len);CHKERRQ(ierr);
202e5c89e4eSSatish Balay     for (i=0; i<len; i++) {
203a297a907SKarl Rupp       if (program[i] == '\"') command[cnt++] = '\\';
204e5c89e4eSSatish Balay       command[cnt++] = program[i];
205e5c89e4eSSatish Balay     }
206e5c89e4eSSatish Balay     command[cnt] = 0;
207a297a907SKarl Rupp 
208e5c89e4eSSatish Balay     ierr = PetscStrcat(command,"\"");CHKERRQ(ierr);
209e5c89e4eSSatish Balay   } else {
210e5c89e4eSSatish Balay     ierr = PetscStrcpy(command,program);CHKERRQ(ierr);
211e5c89e4eSSatish Balay   }
212e5c89e4eSSatish Balay 
213e5c89e4eSSatish Balay   ierr = PetscStrreplace(comm,command,commandt,1024);CHKERRQ(ierr);
214e5c89e4eSSatish Balay 
215e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
216e5c89e4eSSatish Balay   if (!rank) {
217ae15b995SBarry Smith     ierr = PetscInfo1(0,"Running command :%s\n",commandt);CHKERRQ(ierr);
218f23aa3ddSBarry Smith     if (!(fd = popen(commandt,mode))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot run command %s",commandt);
219e5c89e4eSSatish Balay     if (fp) *fp = fd;
220e5c89e4eSSatish Balay   }
221e5c89e4eSSatish Balay   PetscFunctionReturn(0);
222e5c89e4eSSatish Balay }
223e5c89e4eSSatish Balay 
224*74ba8654SBarry Smith #undef __FUNCT__
225*74ba8654SBarry Smith #define __FUNCT__ "PetscPOpenSetMachine"
226*74ba8654SBarry Smith /*@C
227*74ba8654SBarry Smith       PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on
228*74ba8654SBarry Smith 
229*74ba8654SBarry Smith      Logically Collective on MPI_Comm, but only process 0 runs the command
230*74ba8654SBarry Smith 
231*74ba8654SBarry Smith    Input Parameter:
232*74ba8654SBarry Smith .   machine - machine to run command on or NULL to remove previous entry
233*74ba8654SBarry Smith 
234*74ba8654SBarry Smith    Options Database:
235*74ba8654SBarry Smith .   -popen_machine <machine>
236*74ba8654SBarry Smith 
237*74ba8654SBarry Smith    Level: intermediate
238*74ba8654SBarry Smith 
239*74ba8654SBarry Smith .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen()
240*74ba8654SBarry Smith 
241*74ba8654SBarry Smith @*/
242*74ba8654SBarry Smith PetscErrorCode  PetscPOpenSetMachine(const char machine[])
243*74ba8654SBarry Smith {
244*74ba8654SBarry Smith   PetscErrorCode ierr;
245*74ba8654SBarry Smith 
246*74ba8654SBarry Smith   PetscFunctionBegin;
247*74ba8654SBarry Smith   if (machine) {
248*74ba8654SBarry Smith     ierr = PetscStrcpy(PetscPOpenMachine,machine);CHKERRQ(ierr);
249*74ba8654SBarry Smith   } else {
250*74ba8654SBarry Smith     PetscPOpenMachine[0] = 0;
251*74ba8654SBarry Smith   }
252*74ba8654SBarry Smith   PetscFunctionReturn(0);
253*74ba8654SBarry Smith }
254*74ba8654SBarry Smith 
255e5c89e4eSSatish Balay #endif
256