xref: /petsc/src/sys/fileio/mpiuopen.c (revision e8976759b7b43be2087cb81f53885e86f269ef17)
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"
68*e8976759SBarry Smith /*@C
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)
10474ba8654SBarry 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 
17074ba8654SBarry Smith        If machine is not provided will use the value set with PetsPOpenSetMachine() if that was provided, otherwise
17174ba8654SBarry Smith        will use the machine running node zero of the communicator
17274ba8654SBarry Smith 
173e5c89e4eSSatish Balay        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
174e5c89e4eSSatish Balay     will be replaced with relevent values.
175e5c89e4eSSatish Balay 
17674ba8654SBarry 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 */
18974ba8654SBarry Smith   if (PetscPOpenMachine[0] || (machine && machine[0])) {
190e5c89e4eSSatish Balay     ierr = PetscStrcpy(command,"ssh ");CHKERRQ(ierr);
19174ba8654SBarry Smith     if (PetscPOpenMachine[0]) {
19274ba8654SBarry Smith       ierr = PetscStrcat(command,PetscPOpenMachine);CHKERRQ(ierr);
19374ba8654SBarry Smith     } else {
194e5c89e4eSSatish Balay       ierr = PetscStrcat(command,machine);CHKERRQ(ierr);
19574ba8654SBarry 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 
22474ba8654SBarry Smith #undef __FUNCT__
22574ba8654SBarry Smith #define __FUNCT__ "PetscPOpenSetMachine"
22674ba8654SBarry Smith /*@C
22774ba8654SBarry Smith       PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on
22874ba8654SBarry Smith 
22974ba8654SBarry Smith      Logically Collective on MPI_Comm, but only process 0 runs the command
23074ba8654SBarry Smith 
23174ba8654SBarry Smith    Input Parameter:
23274ba8654SBarry Smith .   machine - machine to run command on or NULL to remove previous entry
23374ba8654SBarry Smith 
23474ba8654SBarry Smith    Options Database:
23574ba8654SBarry Smith .   -popen_machine <machine>
23674ba8654SBarry Smith 
23774ba8654SBarry Smith    Level: intermediate
23874ba8654SBarry Smith 
23974ba8654SBarry Smith .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen()
24074ba8654SBarry Smith 
24174ba8654SBarry Smith @*/
24274ba8654SBarry Smith PetscErrorCode  PetscPOpenSetMachine(const char machine[])
24374ba8654SBarry Smith {
24474ba8654SBarry Smith   PetscErrorCode ierr;
24574ba8654SBarry Smith 
24674ba8654SBarry Smith   PetscFunctionBegin;
24774ba8654SBarry Smith   if (machine) {
24874ba8654SBarry Smith     ierr = PetscStrcpy(PetscPOpenMachine,machine);CHKERRQ(ierr);
24974ba8654SBarry Smith   } else {
25074ba8654SBarry Smith     PetscPOpenMachine[0] = 0;
25174ba8654SBarry Smith   }
25274ba8654SBarry Smith   PetscFunctionReturn(0);
25374ba8654SBarry Smith }
25474ba8654SBarry Smith 
255e5c89e4eSSatish Balay #endif
256