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