xref: /petsc/src/sys/fileio/mpiuopen.c (revision 811af0c4b09a35de4306c442f88bd09fdc09897d)
10039db0dSBarry Smith #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for popen() */
2e5c89e4eSSatish Balay /*
34c500f23SPierre Jolivet       Some PETSc utility routines to add simple parallel IO capabilities
4e5c89e4eSSatish Balay */
5c6db04a5SJed Brown #include <petscsys.h>
6e94e781bSJacob Faibussowitsch #include <petsc/private/logimpl.h>
7d0286d30SJed Brown #include <errno.h>
8d0286d30SJed Brown 
9e5c89e4eSSatish Balay /*@C
10e5c89e4eSSatish Balay     PetscFOpen - Has the first process in the communicator open a file;
11e5c89e4eSSatish Balay     all others do nothing.
12e5c89e4eSSatish Balay 
13d083f849SBarry Smith     Logically Collective
14e5c89e4eSSatish Balay 
15e5c89e4eSSatish Balay     Input Parameters:
16e5c89e4eSSatish Balay +   comm - the communicator
17e5c89e4eSSatish Balay .   name - the filename
18e5c89e4eSSatish Balay -   mode - the mode for fopen(), usually "w"
19e5c89e4eSSatish Balay 
20e5c89e4eSSatish Balay     Output Parameter:
21e5c89e4eSSatish Balay .   fp - the file pointer
22e5c89e4eSSatish Balay 
23e5c89e4eSSatish Balay     Level: developer
24e5c89e4eSSatish Balay 
25*811af0c4SBarry Smith     Note:
260298fd71SBarry Smith        NULL (0), "stderr" or "stdout" may be passed in as the filename
27e5c89e4eSSatish Balay 
28e5c89e4eSSatish Balay     Fortran Note:
29e5c89e4eSSatish Balay     This routine is not supported in Fortran.
30e5c89e4eSSatish Balay 
31db781477SPatrick Sanan .seealso: `PetscFClose()`, `PetscSynchronizedFGets()`, `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
32db781477SPatrick Sanan           `PetscFPrintf()`
33e5c89e4eSSatish Balay @*/
349371c9d4SSatish Balay PetscErrorCode PetscFOpen(MPI_Comm comm, const char name[], const char mode[], FILE **fp) {
35e5c89e4eSSatish Balay   PetscMPIInt rank;
36e5c89e4eSSatish Balay   FILE       *fd;
37e5c89e4eSSatish Balay   char        fname[PETSC_MAX_PATH_LEN], tname[PETSC_MAX_PATH_LEN];
38e5c89e4eSSatish Balay 
39e5c89e4eSSatish Balay   PetscFunctionBegin;
409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
41dd400576SPatrick Sanan   if (rank == 0) {
42ace3abfcSBarry Smith     PetscBool isstdout, isstderr;
439566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
449566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
45a297a907SKarl Rupp     if (isstdout || !name) fd = PETSC_STDOUT;
46a297a907SKarl Rupp     else if (isstderr) fd = PETSC_STDERR;
47a297a907SKarl Rupp     else {
48b3f259d6SBarry Smith       PetscBool devnull;
499566063dSJacob Faibussowitsch       PetscCall(PetscStrreplace(PETSC_COMM_SELF, name, tname, PETSC_MAX_PATH_LEN));
509566063dSJacob Faibussowitsch       PetscCall(PetscFixFilename(tname, fname));
519566063dSJacob Faibussowitsch       PetscCall(PetscStrbeginswith(fname, "/dev/null", &devnull));
5248a46eb9SPierre Jolivet       if (devnull) PetscCall(PetscStrcpy(fname, "/dev/null"));
539566063dSJacob Faibussowitsch       PetscCall(PetscInfo(0, "Opening file %s\n", fname));
54e5c89e4eSSatish Balay       fd = fopen(fname, mode);
5528b400f6SJacob Faibussowitsch       PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open file %s", fname);
56e5c89e4eSSatish Balay     }
5702c9f0b5SLisandro Dalcin   } else fd = NULL;
58e5c89e4eSSatish Balay   *fp = fd;
59e5c89e4eSSatish Balay   PetscFunctionReturn(0);
60e5c89e4eSSatish Balay }
61e5c89e4eSSatish Balay 
62e8976759SBarry Smith /*@C
63e5c89e4eSSatish Balay     PetscFClose - Has the first processor in the communicator close a
64e5c89e4eSSatish Balay     file; all others do nothing.
65e5c89e4eSSatish Balay 
66d083f849SBarry Smith     Logically Collective
67e5c89e4eSSatish Balay 
68e5c89e4eSSatish Balay     Input Parameters:
69e5c89e4eSSatish Balay +   comm - the communicator
70e5c89e4eSSatish Balay -   fd - the file, opened with PetscFOpen()
71e5c89e4eSSatish Balay 
72e5c89e4eSSatish Balay    Level: developer
73e5c89e4eSSatish Balay 
74e5c89e4eSSatish Balay     Fortran Note:
75e5c89e4eSSatish Balay     This routine is not supported in Fortran.
76e5c89e4eSSatish Balay 
77db781477SPatrick Sanan .seealso: `PetscFOpen()`
78e5c89e4eSSatish Balay @*/
799371c9d4SSatish Balay PetscErrorCode PetscFClose(MPI_Comm comm, FILE *fd) {
80e5c89e4eSSatish Balay   PetscMPIInt rank;
81ed9cf6e9SBarry Smith   int         err;
82e5c89e4eSSatish Balay 
83e5c89e4eSSatish Balay   PetscFunctionBegin;
849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
85dd400576SPatrick Sanan   if (rank == 0 && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
86ed9cf6e9SBarry Smith     err = fclose(fd);
8728b400f6SJacob Faibussowitsch     PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
88ed9cf6e9SBarry Smith   }
89e5c89e4eSSatish Balay   PetscFunctionReturn(0);
90e5c89e4eSSatish Balay }
91e5c89e4eSSatish Balay 
92e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN)
9374ba8654SBarry Smith static char PetscPOpenMachine[128] = "";
94e5c89e4eSSatish Balay 
95e5c89e4eSSatish Balay /*@C
96*811af0c4SBarry Smith       PetscPClose - Closes (ends) a program on processor zero run with `PetscPOpen()`
97e5c89e4eSSatish Balay 
98d083f849SBarry Smith      Collective, but only process 0 runs the command
99e5c89e4eSSatish Balay 
100e5c89e4eSSatish Balay    Input Parameters:
101e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1020298fd71SBarry Smith -   fp - the file pointer where program input or output may be read or NULL if don't care
103e5c89e4eSSatish Balay 
104e5c89e4eSSatish Balay    Level: intermediate
105e5c89e4eSSatish Balay 
106*811af0c4SBarry Smith    Note:
107e5c89e4eSSatish Balay        Does not work under Windows
108e5c89e4eSSatish Balay 
109db781477SPatrick Sanan .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPOpen()`
110e5c89e4eSSatish Balay @*/
1119371c9d4SSatish Balay PetscErrorCode PetscPClose(MPI_Comm comm, FILE *fd) {
112e5c89e4eSSatish Balay   PetscMPIInt rank;
113e5c89e4eSSatish Balay 
114e5c89e4eSSatish Balay   PetscFunctionBegin;
1159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
116dd400576SPatrick Sanan   if (rank == 0) {
117e5c89e4eSSatish Balay     char buf[1024];
1189371c9d4SSatish Balay     while (fgets(buf, 1024, fd))
1199371c9d4SSatish Balay       ; /* wait till it prints everything */
120016831caSBarry Smith     (void)pclose(fd);
121e5c89e4eSSatish Balay   }
122e5c89e4eSSatish Balay   PetscFunctionReturn(0);
123e5c89e4eSSatish Balay }
124e5c89e4eSSatish Balay 
125e5c89e4eSSatish Balay /*@C
126e5c89e4eSSatish Balay       PetscPOpen - Runs a program on processor zero and sends either its input or output to
127e5c89e4eSSatish Balay           a file.
128e5c89e4eSSatish Balay 
129d083f849SBarry Smith      Logically Collective, but only process 0 runs the command
130e5c89e4eSSatish Balay 
131e5c89e4eSSatish Balay    Input Parameters:
132e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1330298fd71SBarry Smith .   machine - machine to run command on or NULL, or string with 0 in first location
134e5c89e4eSSatish Balay .   program - name of program to run
135e5c89e4eSSatish Balay -   mode - either r or w
136e5c89e4eSSatish Balay 
137e5c89e4eSSatish Balay    Output Parameter:
1380298fd71SBarry Smith .   fp - the file pointer where program input or output may be read or NULL if don't care
139e5c89e4eSSatish Balay 
140e5c89e4eSSatish Balay    Level: intermediate
141e5c89e4eSSatish Balay 
142e5c89e4eSSatish Balay    Notes:
143*811af0c4SBarry Smith        Use `PetscPClose()` to close the file pointer when you are finished with it
144*811af0c4SBarry Smith 
145e5c89e4eSSatish Balay        Does not work under Windows
146e5c89e4eSSatish Balay 
147*811af0c4SBarry Smith        If machine is not provided will use the value set with `PetsPOpenSetMachine()` if that was provided, otherwise
14874ba8654SBarry Smith        will use the machine running node zero of the communicator
14974ba8654SBarry Smith 
150e5c89e4eSSatish Balay        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
151a5b23f4aSJose E. Roman     will be replaced with relevant values.
152e5c89e4eSSatish Balay 
153db781477SPatrick Sanan .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPClose()`, `PetscPOpenSetMachine()`
154e5c89e4eSSatish Balay @*/
1559371c9d4SSatish Balay PetscErrorCode PetscPOpen(MPI_Comm comm, const char machine[], const char program[], const char mode[], FILE **fp) {
156e5c89e4eSSatish Balay   PetscMPIInt rank;
157e5c89e4eSSatish Balay   size_t      i, len, cnt;
158e5c89e4eSSatish Balay   char        commandt[PETSC_MAX_PATH_LEN], command[PETSC_MAX_PATH_LEN];
159e5c89e4eSSatish Balay   FILE       *fd;
160e5c89e4eSSatish Balay 
161e5c89e4eSSatish Balay   PetscFunctionBegin;
162e5c89e4eSSatish Balay   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
16374ba8654SBarry Smith   if (PetscPOpenMachine[0] || (machine && machine[0])) {
1649566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(command, "ssh "));
16574ba8654SBarry Smith     if (PetscPOpenMachine[0]) {
1669566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(command, PetscPOpenMachine));
16774ba8654SBarry Smith     } else {
1689566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(command, machine));
16974ba8654SBarry Smith     }
1709566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(command, " \" export DISPLAY=${DISPLAY}; "));
171e5c89e4eSSatish Balay     /*
172e5c89e4eSSatish Balay         Copy program into command but protect the " with a \ in front of it
173e5c89e4eSSatish Balay     */
1749566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(command, &cnt));
1759566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(program, &len));
176e5c89e4eSSatish Balay     for (i = 0; i < len; i++) {
177a297a907SKarl Rupp       if (program[i] == '\"') command[cnt++] = '\\';
178e5c89e4eSSatish Balay       command[cnt++] = program[i];
179e5c89e4eSSatish Balay     }
180e5c89e4eSSatish Balay     command[cnt] = 0;
181a297a907SKarl Rupp 
1829566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(command, "\""));
183e5c89e4eSSatish Balay   } else {
1849566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(command, program));
185e5c89e4eSSatish Balay   }
186e5c89e4eSSatish Balay 
1879566063dSJacob Faibussowitsch   PetscCall(PetscStrreplace(comm, command, commandt, 1024));
188e5c89e4eSSatish Balay 
1899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
190dd400576SPatrick Sanan   if (rank == 0) {
1919566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Running command :%s\n", commandt));
192cc73adaaSBarry Smith     PetscCheck((fd = popen(commandt, mode)), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot run command %s", commandt);
193e5c89e4eSSatish Balay     if (fp) *fp = fd;
194e5c89e4eSSatish Balay   }
195e5c89e4eSSatish Balay   PetscFunctionReturn(0);
196e5c89e4eSSatish Balay }
197e5c89e4eSSatish Balay 
19874ba8654SBarry Smith /*@C
199*811af0c4SBarry Smith       PetscPOpenSetMachine - Sets the name of the default machine to run `PetscPOpen()` calls on
20074ba8654SBarry Smith 
201d083f849SBarry Smith      Logically Collective, but only process 0 runs the command
20274ba8654SBarry Smith 
20374ba8654SBarry Smith    Input Parameter:
20410699b91SBarry Smith .   machine - machine to run command on or NULL for the current machine
20574ba8654SBarry Smith 
206*811af0c4SBarry Smith    Options Database Key:
20710699b91SBarry Smith .   -popen_machine <machine> - run the process on this machine
20874ba8654SBarry Smith 
20974ba8654SBarry Smith    Level: intermediate
21074ba8654SBarry Smith 
211db781477SPatrick Sanan .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPClose()`, `PetscPOpen()`
21274ba8654SBarry Smith @*/
2139371c9d4SSatish Balay PetscErrorCode PetscPOpenSetMachine(const char machine[]) {
21474ba8654SBarry Smith   PetscFunctionBegin;
21574ba8654SBarry Smith   if (machine) {
2169566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(PetscPOpenMachine, machine));
21774ba8654SBarry Smith   } else {
21874ba8654SBarry Smith     PetscPOpenMachine[0] = 0;
21974ba8654SBarry Smith   }
22074ba8654SBarry Smith   PetscFunctionReturn(0);
22174ba8654SBarry Smith }
22274ba8654SBarry Smith 
223e5c89e4eSSatish Balay #endif
224