Actual source code: mpiuopen.c
petsc-3.7.1 2016-05-15
Report Typos and Errors

      1: #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for popen */
      2: /*
      3:       Some PETSc utilites routines to add simple parallel IO capability
      4: */
      5: #include <petscsys.h>

      7: #include <errno.h>

     11: /*@C
     12:     PetscFOpen - Has the first process in the communicator open a file;
     13:     all others do nothing.

     15:     Logically Collective on MPI_Comm

     17:     Input Parameters:
     18: +   comm - the communicator
     19: .   name - the filename
     20: -   mode - the mode for fopen(), usually "w"

     22:     Output Parameter:
     23: .   fp - the file pointer

     25:     Level: developer

     27:     Notes:
     28:        NULL (0), "stderr" or "stdout" may be passed in as the filename

     30:     Fortran Note:
     31:     This routine is not supported in Fortran.

     33:     Concepts: opening ASCII file
     34:     Concepts: files^opening ASCII

     36: .seealso: PetscFClose(), PetscSynchronizedFGets(), PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
     37:           PetscFPrintf()
     38: @*/
     39: PetscErrorCode  PetscFOpen(MPI_Comm comm,const char name[],const char mode[],FILE **fp)
     40: {
     42:   PetscMPIInt    rank;
     43:   FILE           *fd;
     44:   char           fname[PETSC_MAX_PATH_LEN],tname[PETSC_MAX_PATH_LEN];

     47:   MPI_Comm_rank(comm,&rank);
     48:   if (!rank) {
     49:     PetscBool isstdout,isstderr;
     50:     PetscStrcmp(name,"stdout",&isstdout);
     51:     PetscStrcmp(name,"stderr",&isstderr);
     52:     if (isstdout || !name) fd = PETSC_STDOUT;
     53:     else if (isstderr) fd = PETSC_STDERR;
     54:     else {
     55:       PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);
     56:       PetscFixFilename(tname,fname);
     57:       PetscInfo1(0,"Opening file %s\n",fname);
     58:       fd   = fopen(fname,mode);
     59:       if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file %s\n",fname);
     60:     }
     61:   } else fd = 0;
     62:   *fp = fd;
     63:   return(0);
     64: }

     68: /*@
     69:     PetscFClose - Has the first processor in the communicator close a
     70:     file; all others do nothing.

     72:     Logically Collective on MPI_Comm

     74:     Input Parameters:
     75: +   comm - the communicator
     76: -   fd - the file, opened with PetscFOpen()

     78:    Level: developer

     80:     Fortran Note:
     81:     This routine is not supported in Fortran.

     83:     Concepts: files^closing ASCII
     84:     Concepts: closing file

     86: .seealso: PetscFOpen()
     87: @*/
     88: PetscErrorCode  PetscFClose(MPI_Comm comm,FILE *fd)
     89: {
     91:   PetscMPIInt    rank;
     92:   int            err;

     95:   MPI_Comm_rank(comm,&rank);
     96:   if (!rank && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
     97:     err = fclose(fd);
     98:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
     99:   }
    100:   return(0);
    101: }

    103: #if defined(PETSC_HAVE_POPEN)
    104: static char PetscPOpenMachine[128] = "";

    108: /*@C
    109:       PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()

    111:      Collective on MPI_Comm, but only process 0 runs the command

    113:    Input Parameters:
    114: +   comm - MPI communicator, only processor zero runs the program
    115: -   fp - the file pointer where program input or output may be read or NULL if don't care

    117:    Output Parameters:
    118: .   rval - return value from pclose() or NULL to raise an error on failure

    120:    Level: intermediate

    122:    Notes:
    123:        Does not work under Windows

    125: .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()

    127: @*/
    128: PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd,int *rval)
    129: {
    131:   PetscMPIInt    rank;
    132:   int            err;

    135:   MPI_Comm_rank(comm,&rank);
    136:   if (!rank) {
    137:     char buf[1024];
    138:     while (fgets(buf,1024,fd)) ; /* wait till it prints everything */
    139:     err = pclose(fd);
    140:     if (rval) *rval = err;
    141:     else if (err) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SYS,"pclose() failed with error code %d, errno %d",err,errno);
    142:   }
    143:   return(0);
    144: }

    149: /*@C
    150:       PetscPOpen - Runs a program on processor zero and sends either its input or output to
    151:           a file.

    153:      Logically Collective on MPI_Comm, but only process 0 runs the command

    155:    Input Parameters:
    156: +   comm - MPI communicator, only processor zero runs the program
    157: .   machine - machine to run command on or NULL, or string with 0 in first location
    158: .   program - name of program to run
    159: -   mode - either r or w

    161:    Output Parameter:
    162: .   fp - the file pointer where program input or output may be read or NULL if don't care

    164:    Level: intermediate

    166:    Notes:
    167:        Use PetscPClose() to close the file pointer when you are finished with it
    168:        Does not work under Windows

    170:        If machine is not provided will use the value set with PetsPOpenSetMachine() if that was provided, otherwise
    171:        will use the machine running node zero of the communicator

    173:        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
    174:     will be replaced with relevent values.

    176: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpenSetMachine()

    178: @*/
    179: PetscErrorCode  PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
    180: {
    182:   PetscMPIInt    rank;
    183:   size_t         i,len,cnt;
    184:   char           commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
    185:   FILE           *fd;

    188:   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
    189:   if (PetscPOpenMachine[0] || (machine && machine[0])) {
    190:     PetscStrcpy(command,"ssh ");
    191:     if (PetscPOpenMachine[0]) {
    192:       PetscStrcat(command,PetscPOpenMachine);
    193:     } else {
    194:       PetscStrcat(command,machine);
    195:     }
    196:     PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");
    197:     /*
    198:         Copy program into command but protect the " with a \ in front of it
    199:     */
    200:     PetscStrlen(command,&cnt);
    201:     PetscStrlen(program,&len);
    202:     for (i=0; i<len; i++) {
    203:       if (program[i] == '\"') command[cnt++] = '\\';
    204:       command[cnt++] = program[i];
    205:     }
    206:     command[cnt] = 0;

    208:     PetscStrcat(command,"\"");
    209:   } else {
    210:     PetscStrcpy(command,program);
    211:   }

    213:   PetscStrreplace(comm,command,commandt,1024);

    215:   MPI_Comm_rank(comm,&rank);
    216:   if (!rank) {
    217:     PetscInfo1(0,"Running command :%s\n",commandt);
    218:     if (!(fd = popen(commandt,mode))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot run command %s",commandt);
    219:     if (fp) *fp = fd;
    220:   }
    221:   return(0);
    222: }

    226: /*@C
    227:       PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on

    229:      Logically Collective on MPI_Comm, but only process 0 runs the command

    231:    Input Parameter:
    232: .   machine - machine to run command on or NULL to remove previous entry

    234:    Options Database:
    235: .   -popen_machine <machine>

    237:    Level: intermediate

    239: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen()

    241: @*/
    242: PetscErrorCode  PetscPOpenSetMachine(const char machine[])
    243: {

    247:   if (machine) {
    248:     PetscStrcpy(PetscPOpenMachine,machine);
    249:   } else {
    250:     PetscPOpenMachine[0] = 0;
    251:   }
    252:   return(0);
    253: }

    255: #endif