#define PETSC_DLL /* Utilites routines to add simple ASCII IO capability. */ #include "src/sys/fileio/mprint.h" /* If petsc_history is on, then all Petsc*Printf() results are saved if the appropriate (usually .petschistory) file. */ extern FILE *petsc_history; /* Allows one to overwrite where standard out is sent. For example PETSC_STDOUT = fopen("/dev/ttyXX","w") will cause all standard out writes to go to terminal XX; assuming you have write permission there */ FILE *PETSC_STDOUT = 0; /* Allows one to overwrite where standard error is sent. For example PETSC_STDERR = fopen("/dev/ttyXX","w") will cause all standard error writes to go to terminal XX; assuming you have write permission there */ FILE *PETSC_STDERR = 0; /* Used to output to Zope */ FILE *PETSC_ZOPEFD = 0; #undef __FUNCT__ #define __FUNCT__ "PetscFormatConvert" PetscErrorCode PETSC_DLLEXPORT PetscFormatConvert(const char *format,char *newformat,PetscInt size) { PetscInt i = 0,j = 0; while (format[i] && i < size-1) { if (format[i] == '%' && format[i+1] == 'D') { newformat[j++] = '%'; #if !defined(PETSC_USE_64BIT_INDICES) newformat[j++] = 'd'; #else newformat[j++] = 'l'; newformat[j++] = 'l'; newformat[j++] = 'd'; #endif i += 2; } else if (format[i] == '%' && format[i+1] >= '1' && format[i+1] <= '9' && format[i+2] == 'D') { newformat[j++] = '%'; newformat[j++] = format[i+1]; #if !defined(PETSC_USE_64BIT_INDICES) newformat[j++] = 'd'; #else newformat[j++] = 'l'; newformat[j++] = 'l'; newformat[j++] = 'd'; #endif i += 3; } else if (format[i] == '%' && format[i+1] == 'G') { newformat[j++] = '%'; #if defined(PETSC_USE_INT) newformat[j++] = 'd'; #elif !defined(PETSC_USE_LONG_DOUBLE) newformat[j++] = 'g'; #else newformat[j++] = 'L'; newformat[j++] = 'g'; #endif i += 2; }else { newformat[j++] = format[i++]; } } newformat[j] = 0; return 0; } #undef __FUNCT__ #define __FUNCT__ "PetscVSNPrintf" /* No error handling because may be called by error handler */ PetscErrorCode PETSC_DLLEXPORT PetscVSNPrintf(char *str,size_t len,const char *format,va_list Argp) { /* no malloc since may be called by error handler */ char newformat[8*1024]; size_t length; PetscErrorCode ierr; PetscFormatConvert(format,newformat,8*1024); ierr = PetscStrlen(newformat, &length);CHKERRQ(ierr); if (length > len) { newformat[len] = '\0'; } #if defined(PETSC_HAVE_VPRINTF_CHAR) vsprintf(str,newformat,(char *)Argp); #else vsprintf(str,newformat,Argp); #endif return 0; } #undef __FUNCT__ #define __FUNCT__ "PetscZopeLog" PetscErrorCode PETSC_DLLEXPORT PetscZopeLog(const char *format,va_list Argp){ /* no malloc since may be called by error handler */ char newformat[8*1024]; char log[8*1024]; extern FILE * PETSC_ZOPEFD; char logstart[] = " <<>>"; size_t len; size_t formatlen; PetscFormatConvert(format,newformat,8*1024); PetscStrlen(logstart, &len); PetscMemcpy(log, logstart, len); PetscStrlen(newformat, &formatlen); PetscMemcpy(&(log[len]), newformat, formatlen); if(PETSC_ZOPEFD != NULL){ #if defined(PETSC_HAVE_VPRINTF_CHAR) vfprintf(PETSC_ZOPEFD,log,(char *)Argp); #else vfprintf(PETSC_ZOPEFD,log,Argp); fflush(PETSC_ZOPEFD); #endif } return 0; } #undef __FUNCT__ #define __FUNCT__ "PetscVFPrintf" /* All PETSc standard out and error messages are sent through this function; so, in theory, this can can be replaced with something that does not simply write to a file. Note: For error messages this may be called by a process, for regular standard out it is called only by process 0 of a given communicator No error handling because may be called by error handler */ PetscErrorCode PETSC_DLLEXPORT PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp) { /* no malloc since may be called by error handler */ char newformat[8*1024]; extern FILE *PETSC_ZOPEFD; PetscFormatConvert(format,newformat,8*1024); if(PETSC_ZOPEFD != NULL && PETSC_ZOPEFD != PETSC_STDOUT){ va_list s; #if defined(PETSC_HAVE_VA_COPY) va_copy(s, Argp); #elif defined(PETSC_HAVE___VA_COPY) __va_copy(s, Argp); #else SETERRQ(PETSC_ERR_SUP_SYS,"Zope not supported due to missing va_copy()"); #endif #if defined(PETSC_HAVE_VPRINTF_CHAR) vfprintf(PETSC_ZOPEFD,newformat,(char *)s); #else vfprintf(PETSC_ZOPEFD,newformat,s); fflush(PETSC_ZOPEFD); #endif } #if defined(PETSC_HAVE_VPRINTF_CHAR) vfprintf(fd,newformat,(char *)Argp); #else vfprintf(fd,newformat,Argp); fflush(fd); #endif return 0; } #undef __FUNCT__ #define __FUNCT__ "PetscSNPrintf" /*@C PetscSNPrintf - Prints to a string of given length Not Collective Input Parameters: + str - the string to print to . len - the length of str . format - the usual printf() format string - any arguments Level: intermediate .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() @*/ PetscErrorCode PETSC_DLLEXPORT PetscSNPrintf(char *str,size_t len,const char format[],...) { PetscErrorCode ierr; va_list Argp; PetscFunctionBegin; va_start(Argp,format); ierr = PetscVSNPrintf(str,len,format,Argp);CHKERRQ(ierr); PetscFunctionReturn(0); } /* ----------------------------------------------------------------------- */ PrintfQueue queue = 0,queuebase = 0; int queuelength = 0; FILE *queuefile = PETSC_NULL; #undef __FUNCT__ #define __FUNCT__ "PetscSynchronizedPrintf" /*@C PetscSynchronizedPrintf - Prints synchronized output from several processors. Output of the first processor is followed by that of the second, etc. Not Collective Input Parameters: + comm - the communicator - format - the usual printf() format string Level: intermediate Notes: REQUIRES a intervening call to PetscSynchronizedFlush() for the information from all the processors to be printed. Fortran Note: The call sequence is PetscSynchronizedPrintf(PetscViewer, character(*), PetscErrorCode ierr) from Fortran. That is, you can only pass a single character string from Fortran. The length of the formatted message cannot exceed QUEUESTRINGSIZE characters. .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() @*/ PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...) { PetscErrorCode ierr; PetscMPIInt rank; PetscFunctionBegin; ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); /* First processor prints immediately to stdout */ if (!rank) { va_list Argp; va_start(Argp,format); ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); if (petsc_history) { ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); } va_end(Argp); } else { /* other processors add to local queue */ va_list Argp; PrintfQueue next; ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr); if (queue) {queue->next = next; queue = next; queue->next = 0;} else {queuebase = queue = next;} queuelength++; va_start(Argp,format); ierr = PetscMemzero(next->string,QUEUESTRINGSIZE);CHKERRQ(ierr); ierr = PetscVSNPrintf(next->string,QUEUESTRINGSIZE,format,Argp);CHKERRQ(ierr); va_end(Argp); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "PetscSynchronizedFPrintf" /*@C PetscSynchronizedFPrintf - Prints synchronized output to the specified file from several processors. Output of the first processor is followed by that of the second, etc. Not Collective Input Parameters: + comm - the communicator . fd - the file pointer - format - the usual printf() format string Level: intermediate Notes: REQUIRES a intervening call to PetscSynchronizedFlush() for the information from all the processors to be printed. The length of the formatted message cannot exceed QUEUESTRINGSIZE characters. Contributed by: Matthew Knepley .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(), PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() @*/ PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFPrintf(MPI_Comm comm,FILE* fp,const char format[],...) { PetscErrorCode ierr; PetscMPIInt rank; PetscFunctionBegin; ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); /* First processor prints immediately to fp */ if (!rank) { va_list Argp; va_start(Argp,format); ierr = (*PetscVFPrintf)(fp,format,Argp);CHKERRQ(ierr); queuefile = fp; if (petsc_history) { ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); } va_end(Argp); } else { /* other processors add to local queue */ va_list Argp; PrintfQueue next; ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr); if (queue) {queue->next = next; queue = next; queue->next = 0;} else {queuebase = queue = next;} queuelength++; va_start(Argp,format); ierr = PetscMemzero(next->string,QUEUESTRINGSIZE);CHKERRQ(ierr); ierr = PetscVSNPrintf(next->string,QUEUESTRINGSIZE,format,Argp);CHKERRQ(ierr); va_end(Argp); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "PetscSynchronizedFlush" /*@ PetscSynchronizedFlush - Flushes to the screen output from all processors involved in previous PetscSynchronizedPrintf() calls. Collective on MPI_Comm Input Parameters: . comm - the communicator Level: intermediate Notes: Usage of PetscSynchronizedPrintf() and PetscSynchronizedFPrintf() with different MPI communicators REQUIRES an intervening call to PetscSynchronizedFlush(). .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() @*/ PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFlush(MPI_Comm comm) { PetscErrorCode ierr; PetscMPIInt rank,size,tag,i,j,n; char message[QUEUESTRINGSIZE]; MPI_Status status; FILE *fd; PetscFunctionBegin; ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); /* First processor waits for messages from all other processors */ if (!rank) { if (queuefile) { fd = queuefile; } else { fd = PETSC_STDOUT; } for (i=1; istring,QUEUESTRINGSIZE,MPI_CHAR,0,tag,comm);CHKERRQ(ierr); previous = next; next = next->next; ierr = PetscFree(previous);CHKERRQ(ierr); } queue = 0; queuelength = 0; } ierr = PetscCommDestroy(&comm);CHKERRQ(ierr); PetscFunctionReturn(0); } /* ---------------------------------------------------------------------------------------*/ #undef __FUNCT__ #define __FUNCT__ "PetscFPrintf" /*@C PetscFPrintf - Prints to a file, only from the first processor in the communicator. Not Collective Input Parameters: + comm - the communicator . fd - the file pointer - format - the usual printf() format string Level: intermediate Fortran Note: This routine is not supported in Fortran. Concepts: printing^in parallel Concepts: printf^in parallel .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush() @*/ PetscErrorCode PETSC_DLLEXPORT PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...) { PetscErrorCode ierr; PetscMPIInt rank; PetscFunctionBegin; ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); if (!rank) { va_list Argp; va_start(Argp,format); ierr = (*PetscVFPrintf)(fd,format,Argp);CHKERRQ(ierr); if (petsc_history) { ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); } va_end(Argp); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "PetscPrintf" /*@C PetscPrintf - Prints to standard out, only from the first processor in the communicator. Not Collective Input Parameters: + comm - the communicator - format - the usual printf() format string Level: intermediate Fortran Note: The call sequence is PetscPrintf(PetscViewer, character(*), PetscErrorCode ierr) from Fortran. That is, you can only pass a single character string from Fortran. Notes: %A is replace with %g unless the value is < 1.e-12 when it is replaced with < 1.e-12 Concepts: printing^in parallel Concepts: printf^in parallel .seealso: PetscFPrintf(), PetscSynchronizedPrintf() @*/ PetscErrorCode PETSC_DLLEXPORT PetscPrintf(MPI_Comm comm,const char format[],...) { PetscErrorCode ierr; PetscMPIInt rank; size_t len; char *nformat,*sub1,*sub2; PetscReal value; PetscFunctionBegin; if (!comm) comm = PETSC_COMM_WORLD; ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); if (!rank) { va_list Argp; va_start(Argp,format); ierr = PetscStrstr(format,"%A",&sub1);CHKERRQ(ierr); if (sub1) { ierr = PetscStrstr(format,"%",&sub2);CHKERRQ(ierr); if (sub1 != sub2) SETERRQ(PETSC_ERR_ARG_WRONG,"%%A format must be first in format string"); ierr = PetscStrlen(format,&len);CHKERRQ(ierr); ierr = PetscMalloc((len+16)*sizeof(char),&nformat);CHKERRQ(ierr); ierr = PetscStrcpy(nformat,format);CHKERRQ(ierr); ierr = PetscStrstr(nformat,"%",&sub2);CHKERRQ(ierr); sub2[0] = 0; value = (double)va_arg(Argp,double); if (PetscAbsReal(value) < 1.e-12) { ierr = PetscStrcat(nformat,"< 1.e-12");CHKERRQ(ierr); } else { ierr = PetscStrcat(nformat,"%g");CHKERRQ(ierr); va_end(Argp); va_start(Argp,format); } ierr = PetscStrcat(nformat,sub1+2);CHKERRQ(ierr); } else { nformat = (char*)format; } ierr = (*PetscVFPrintf)(PETSC_STDOUT,nformat,Argp);CHKERRQ(ierr); if (petsc_history) { ierr = (*PetscVFPrintf)(petsc_history,nformat,Argp);CHKERRQ(ierr); } va_end(Argp); if (sub1) {ierr = PetscFree(nformat);CHKERRQ(ierr);} } PetscFunctionReturn(0); } /* ---------------------------------------------------------------------------------------*/ #undef __FUNCT__ #define __FUNCT__ "PetscHelpPrintfDefault" PetscErrorCode PETSC_DLLEXPORT PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...) { PetscErrorCode ierr; PetscMPIInt rank; PetscFunctionBegin; if (!comm) comm = PETSC_COMM_WORLD; ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); if (!rank) { va_list Argp; va_start(Argp,format); ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); if (petsc_history) { ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); } va_end(Argp); } PetscFunctionReturn(0); } /* ---------------------------------------------------------------------------------------*/ #undef __FUNCT__ #define __FUNCT__ "PetscSynchronizedFGets" /*@C PetscSynchronizedFGets - Several processors all get the same line from a file. Collective on MPI_Comm Input Parameters: + comm - the communicator . fd - the file pointer - len - the length of the output buffer Output Parameter: . string - the line read from the file Level: intermediate .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() @*/ PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFGets(MPI_Comm comm,FILE* fp,size_t len,char string[]) { PetscErrorCode ierr; PetscMPIInt rank; PetscFunctionBegin; ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); if (!rank) { fgets(string,len,fp); } ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr); PetscFunctionReturn(0); }