/* PetscInfo() is contained in a different file from the other profiling to allow it to be replaced at link time by an alternative routine. */ #include /*I "petscsys.h" I*/ /* The next set of variables determine which, if any, PetscInfo() calls are used. If PetscLogPrintInfo is false, no info messages are printed. If PetscInfoFlags[OBJECT_CLASSID - PETSC_SMALLEST_CLASSID] is zero, no messages related to that object are printed. OBJECT_CLASSID is, for example, MAT_CLASSID. Note for developers: the PetscInfoFlags array is currently 160 entries large, to ensure headroom. Perhaps it is worth dynamically allocating this array intelligently rather than just some big number. PetscInfoFilename determines where PetscInfo() output is piped. PetscInfoClassnames holds a char array of classes which are filtered out/for in PetscInfo() calls. */ const char * const PetscInfoCommFlags[] = {"all", "no_self", "only_self", "PetscInfoCommFlag", "PETSC_INFO_COMM_", NULL}; static PetscBool PetscInfoClassesLocked = PETSC_FALSE, PetscInfoInvertClasses = PETSC_FALSE, PetscInfoClassesSet = PETSC_FALSE; static char **PetscInfoClassnames = NULL; static char *PetscInfoFilename = NULL; static PetscInt PetscInfoNumClasses = -1; static PetscInfoCommFlag PetscInfoCommFilter = PETSC_INFO_COMM_ALL; static int PetscInfoFlags[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; PetscBool PetscLogPrintInfo = PETSC_FALSE; FILE *PetscInfoFile = NULL; /*@ PetscInfoEnabled - Checks whether a given OBJECT_CLASSID is allowed to print using PetscInfo() Not Collective Input Parameters: . classid - PetscClassid retrieved from a PetscObject e.g. VEC_CLASSID Output Parameter: . enabled - PetscBool indicating whether this classid is allowed to print Notes: Use PETSC_SMALLEST_CLASSID to check if "sys" PetscInfo() calls are enabled. When PETSc is configured with debugging support this function checks if classid >= PETSC_SMALLEST_CLASSID, otherwise it assumes valid classid. Level: advanced .seealso: PetscInfo(), PetscInfoAllow(), PetscInfoGetInfo(), PetscObjectGetClassid() @*/ PetscErrorCode PetscInfoEnabled(PetscClassId classid, PetscBool *enabled) { PetscFunctionBegin; if (classid < PETSC_SMALLEST_CLASSID) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Classid (current: %d) must be equal to or greater than PETSC_SMALLEST_CLASSID", classid); *enabled = (PetscBool) (PetscLogPrintInfo && PetscInfoFlags[classid - PETSC_SMALLEST_CLASSID]); PetscFunctionReturn(0); } /*@ PetscInfoAllow - Enables/disables PetscInfo() messages Not Collective Input Parameter: . flag - PETSC_TRUE or PETSC_FALSE Level: advanced .seealso: PetscInfo(), PetscInfoEnabled(), PetscInfoGetInfo(), PetscInfoSetFromOptions() @*/ PetscErrorCode PetscInfoAllow(PetscBool flag) { PetscFunctionBegin; PetscLogPrintInfo = flag; PetscFunctionReturn(0); } /*@C PetscInfoSetFile - Sets the printing destination for all PetscInfo() calls Not Collective Input Parameters: + filename - Name of the file where PetscInfo() will print to - mode - Write mode passed to PetscFOpen() Notes: Use filename=NULL to set PetscInfo() to write to PETSC_STDOUT. Level: advanced .seealso: PetscInfo(), PetscInfoSetFile(), PetscInfoSetFromOptions(), PetscFOpen() @*/ PetscErrorCode PetscInfoSetFile(const char filename[], const char mode[]) { char fname[PETSC_MAX_PATH_LEN], tname[11]; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; if (!PetscInfoFile) PetscInfoFile = PETSC_STDOUT; ierr = PetscFree(PetscInfoFilename);CHKERRQ(ierr); if (filename) { PetscBool oldflag; PetscValidCharPointer(filename, 1); ierr = PetscFixFilename(filename, fname);CHKERRQ(ierr); ierr = PetscStrallocpy(fname, &PetscInfoFilename);CHKERRQ(ierr); ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank);CHKERRMPI(ierr); sprintf(tname, ".%d", rank); ierr = PetscStrcat(fname, tname);CHKERRQ(ierr); oldflag = PetscLogPrintInfo; PetscLogPrintInfo = PETSC_FALSE; ierr = PetscFOpen(MPI_COMM_SELF, fname, mode, &PetscInfoFile);CHKERRQ(ierr); PetscLogPrintInfo = oldflag; /* PetscFOpen will write to PETSC_STDOUT and not PetscInfoFile here, so we disable the PetscInfo call inside it, and call it afterwards so that it actually writes to file */ ierr = PetscInfo1(NULL, "Opened PetscInfo file %s\n", fname);CHKERRQ(ierr); } PetscFunctionReturn(0); } /*@C PetscInfoGetFile - Gets the name and FILE pointer of the file where PetscInfo() prints to Not Collective Output Parameters: + filename - The name of the output file - InfoFile - The FILE pointer for the output file Level: advanced Note: This routine allocates and copies the filename so that the filename survives PetscInfoDestroy(). The user is therefore responsible for freeing the allocated filename pointer afterwards. Fortran Note: This routine is not supported in Fortran. .seealso: PetscInfo(), PetscInfoSetFile(), PetscInfoSetFromOptions(), PetscInfoDestroy() @*/ PetscErrorCode PetscInfoGetFile(char **filename, FILE **InfoFile) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(filename, 1); PetscValidPointer(InfoFile, 2); ierr = PetscStrallocpy(PetscInfoFilename, filename);CHKERRQ(ierr); *InfoFile = PetscInfoFile; PetscFunctionReturn(0); } /*@C PetscInfoSetClasses - Sets the classes which PetscInfo() is filtered for/against Not Collective Input Parameters: + exclude - Whether or not to invert the filter, i.e. if exclude is true, PetscInfo() will print from every class that is NOT one of the classes specified . N - Number of classes to filter for (size of classnames) - classnames - String array containing the names of classes to filter for, e.g. "vec" Notes: Not for use in Fortran This function CANNOT be called after PetscInfoGetClass() or PetscInfoProcessClass() has been called. Names in the classnames list should correspond to the names returned by PetscObjectGetClassName(). This function only sets the list of class names. The actual filtering is deferred to PetscInfoProcessClass(), except of sys which is processed right away. The reason for this is that we need to set the list of included/excluded classes before their classids are known. Typically the classid is assigned and PetscInfoProcessClass() called in InitializePackage() (e.g. VecInitializePackage()). Level: developer .seealso: PetscInfo(), PetscInfoGetClass(), PetscInfoProcessClass(), PetscInfoSetFromOptions(), PetscStrToArray(), PetscObjectGetName() @*/ PetscErrorCode PetscInfoSetClasses(PetscBool exclude, PetscInt N, const char *const *classnames) { PetscErrorCode ierr; PetscFunctionBegin; if (PetscInfoClassesLocked) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscInfoSetClasses() cannot be called after PetscInfoGetClass() or PetscInfoProcessClass()"); ierr = PetscStrNArrayDestroy(PetscInfoNumClasses, &PetscInfoClassnames);CHKERRQ(ierr); ierr = PetscStrNArrayallocpy(N, classnames, &PetscInfoClassnames);CHKERRQ(ierr); PetscInfoNumClasses = N; PetscInfoInvertClasses = exclude; { /* Process sys class right away */ PetscClassId sysclassid = PETSC_SMALLEST_CLASSID; ierr = PetscInfoProcessClass("sys", 1, &sysclassid);CHKERRQ(ierr); } PetscInfoClassesSet = PETSC_TRUE; PetscFunctionReturn(0); } /*@C PetscInfoGetClass - Indicates whether the provided classname is marked as a filter in PetscInfo() as set by PetscInfoSetClasses() Not Collective Input Parameter: . classname - Name of the class to search for Output Parameter: . found - PetscBool indicating whether the classname was found Notes: Use PetscObjectGetName() to retrieve an appropriate classname Level: developer .seealso: PetscInfo(), PetscInfoSetClasses(), PetscInfoSetFromOptions(), PetscObjectGetName() @*/ PetscErrorCode PetscInfoGetClass(const char *classname, PetscBool *found) { PetscInt idx; PetscErrorCode ierr; PetscFunctionBegin; PetscValidCharPointer(classname,1); ierr = PetscEListFind(PetscInfoNumClasses, (const char *const *) PetscInfoClassnames, classname ? classname : "sys", &idx, found);CHKERRQ(ierr); PetscInfoClassesLocked = PETSC_TRUE; PetscFunctionReturn(0); } /*@ PetscInfoGetInfo - Returns the current state of several important flags for PetscInfo() Not Collective Output Parameters: + infoEnabled - PETSC_TRUE if PetscInfoAllow(PETSC_TRUE) has been called . classesSet - PETSC_TRUE if the list of classes to filter for has been set . exclude - PETSC_TRUE if the class filtering for PetscInfo() is inverted . locked - PETSC_TRUE if the list of classes to filter for has been locked - commSelfFlag - Enum indicating whether PetscInfo() will print for communicators of size 1, any size != 1, or all communicators Notes: Initially commSelfFlag = PETSC_INFO_COMM_ALL Level: developer .seealso: PetscInfo(), PetscInfoAllow(), PetscInfoSetFilterCommSelf, PetscInfoSetFromOptions() @*/ PetscErrorCode PetscInfoGetInfo(PetscBool *infoEnabled, PetscBool *classesSet, PetscBool *exclude, PetscBool *locked, PetscInfoCommFlag *commSelfFlag) { PetscFunctionBegin; if (infoEnabled) *infoEnabled = PetscLogPrintInfo; if (classesSet) *classesSet = PetscInfoClassesSet; if (exclude) *exclude = PetscInfoInvertClasses; if (locked) *locked = PetscInfoClassesLocked; if (commSelfFlag) *commSelfFlag = PetscInfoCommFilter; PetscFunctionReturn(0); } /*@C PetscInfoProcessClass - Activates or deactivates a class based on the filtering status of PetscInfo() Not Collective Input Parameters: + classname - Name of the class to activate/deactivate PetscInfo() for . numClassID - Number of entries in classIDs - classIDs - Array containing all of the PetscClassids associated with classname Level: developer .seealso: PetscInfo(), PetscInfoActivateClass(), PetscInfoDeactivateClass(), PetscInfoSetFromOptions() @*/ PetscErrorCode PetscInfoProcessClass(const char classname[], PetscInt numClassID, PetscClassId classIDs[]) { PetscInt i; PetscBool enabled, exclude, found, opt, pkg; char logList[256]; PetscErrorCode ierr; PetscFunctionBegin; PetscValidCharPointer(classname, 1); ierr = PetscInfoGetInfo(&enabled, NULL, &exclude, NULL, NULL);CHKERRQ(ierr); /* -info_exclude is DEPRECATED */ ierr = PetscOptionsGetString(NULL,NULL,"-info_exclude",logList,sizeof(logList),&opt);CHKERRQ(ierr); if (opt) { ierr = PetscStrInList(classname,logList,',',&pkg);CHKERRQ(ierr); if (pkg) { for (i = 0; i < numClassID; ++i) { ierr = PetscInfoDeactivateClass(classIDs[i]);CHKERRQ(ierr); } } } ierr = PetscInfoGetClass(classname, &found);CHKERRQ(ierr); if ((found && exclude) || (!found && !exclude)) { if (PetscInfoNumClasses > 0) { /* Check if -info was called empty */ for (i = 0; i < numClassID; ++i) { ierr = PetscInfoDeactivateClass(classIDs[i]);CHKERRQ(ierr); } } } else { for (i = 0; i < numClassID; ++i) { ierr = PetscInfoActivateClass(classIDs[i]);CHKERRQ(ierr); } } PetscFunctionReturn(0); } /*@ PetscInfoSetFilterCommSelf - Sets PetscInfoCommFlag enum to determine communicator filtering for PetscInfo() Not Collective Input Parameter: . commSelfFlag - Enum value indicating method with which to filter PetscInfo() based on the size of the communicator of the object calling PetscInfo() Level: advanced .seealso: PetscInfo(), PetscInfoGetInfo() @*/ PetscErrorCode PetscInfoSetFilterCommSelf(PetscInfoCommFlag commSelfFlag) { PetscFunctionBegin; PetscInfoCommFilter = commSelfFlag; PetscFunctionReturn(0); } /*@ PetscInfoSetFromOptions - Configure PetscInfo() using command line options, enabling or disabling various calls to PetscInfo() Not Collective Input Parameter: . options - Options database, use NULL for default global database Options Database Keys: . -info [filename][:[~][:[~]self]] - specify which informative messages are printed, See PetscInfo(). Notes: This function is called automatically during PetscInitialize() so users usually do not need to call it themselves. Level: advanced .seealso: PetscInfo(), PetscInfoAllow(), PetscInfoSetFile(), PetscInfoSetClasses(), PetscInfoSetFilterCommSelf(), PetscInfoDestroy() @*/ PetscErrorCode PetscInfoSetFromOptions(PetscOptions options) { char optstring[PETSC_MAX_PATH_LEN], *loc0_ = NULL, *loc1_ = NULL, *loc2_ = NULL; char **loc1_array = NULL; PetscBool set, loc1_invert = PETSC_FALSE, loc2_invert = PETSC_FALSE, foundSelf = PETSC_FALSE; size_t size_loc0_ = 0, size_loc1_ = 0, size_loc2_ = 0; int nLoc1_ = 0; PetscInfoCommFlag commSelfFlag = PETSC_INFO_COMM_ALL; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscOptionsDeprecated_Private(NULL,"-info_exclude", NULL, "3.13", "Use -info instead");CHKERRQ(ierr); ierr = PetscOptionsGetString(options, NULL, "-info", optstring, sizeof(optstring), &set);CHKERRQ(ierr); if (set) { PetscInfoClassesSet = PETSC_TRUE; ierr = PetscInfoAllow(PETSC_TRUE);CHKERRQ(ierr); ierr = PetscStrallocpy(optstring,&loc0_);CHKERRQ(ierr); ierr = PetscStrchr(loc0_,':',&loc1_);CHKERRQ(ierr); if (loc1_) { *loc1_++ = 0; if (*loc1_ == '~') { loc1_invert = PETSC_TRUE; ++loc1_; } ierr = PetscStrchr(loc1_,':',&loc2_);CHKERRQ(ierr); } if (loc2_) { *loc2_++ = 0; if (*loc2_ == '~') { loc2_invert = PETSC_TRUE; ++loc2_; } } ierr = PetscStrlen(loc0_, &size_loc0_);CHKERRQ(ierr); ierr = PetscStrlen(loc1_, &size_loc1_);CHKERRQ(ierr); ierr = PetscStrlen(loc2_, &size_loc2_);CHKERRQ(ierr); if (size_loc1_) { ierr = PetscStrtolower(loc1_);CHKERRQ(ierr); ierr = PetscStrToArray(loc1_, ',', &nLoc1_, &loc1_array);CHKERRQ(ierr); } if (size_loc2_) { ierr = PetscStrtolower(loc2_);CHKERRQ(ierr); ierr = PetscStrcmp("self", loc2_, &foundSelf);CHKERRQ(ierr); if (foundSelf) { if (loc2_invert) { commSelfFlag = PETSC_INFO_COMM_NO_SELF; } else { commSelfFlag = PETSC_INFO_COMM_ONLY_SELF; } } } ierr = PetscInfoSetFile(size_loc0_ ? loc0_ : NULL, "w");CHKERRQ(ierr); ierr = PetscInfoSetClasses(loc1_invert, (PetscInt) nLoc1_, (const char *const *) loc1_array);CHKERRQ(ierr); ierr = PetscInfoSetFilterCommSelf(commSelfFlag);CHKERRQ(ierr); ierr = PetscStrToArrayDestroy(nLoc1_, loc1_array);CHKERRQ(ierr); ierr = PetscFree(loc0_);CHKERRQ(ierr); } PetscFunctionReturn(0); } /*@ PetscInfoDestroy - Destroys and resets internal PetscInfo() data structures. Not Collective Notes: This is automatically called in PetscFinalize(). Useful for changing filters mid-program, or culling subsequent PetscInfo() calls down the line. Level: developer .seealso: PetscInfo(), PetscInfoSetFromOptions() @*/ PetscErrorCode PetscInfoDestroy(void) { PetscErrorCode ierr; int err; size_t i; PetscFunctionBegin; ierr = PetscInfoAllow(PETSC_FALSE);CHKERRQ(ierr); ierr = PetscStrNArrayDestroy(PetscInfoNumClasses, &PetscInfoClassnames);CHKERRQ(ierr); err = fflush(PetscInfoFile); if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); if (PetscInfoFilename) { ierr = PetscFClose(MPI_COMM_SELF, PetscInfoFile);CHKERRQ(ierr); } ierr = PetscFree(PetscInfoFilename);CHKERRQ(ierr); for (i=0; i PetscErrorCode PetscInfo(PetscObject obj, const char message[]) PetscErrorCode PetscInfo1(PetscObject obj, const char formatmessage[],arg1) PetscErrorCode PetscInfo2(PetscObject obj, const char formatmessage[],arg1,arg2) ... Collective on obj Input Parameters: + obj - object most closely associated with the logging statement or NULL . message - logging message . formatmessage - logging message using standard "printf" format - arg1, arg2, ... - arguments of the format Notes: PetscInfo() prints only from the first processor in the communicator of obj. If obj is NULL, the PETSC_COMM_SELF communicator is used, i.e. every rank of PETSC_COMM_WORLD prints the message. Extent of the printed messages can be controlled using the option database key -info as follows. $ -info [filename][:[~][:[~]self]] No filename means standard output PETSC_STDOUT is used. The optional is a comma separated list of enabled classes, e.g. vec,mat,ksp. If this list is not specified, all classes are enabled. Prepending the list with ~ means inverted selection, i.e. all classes except the listed are enabled. A special classname sys relates to PetscInfo() with obj being NULL. The optional self keyword specifies that PetscInfo() is enabled only for communicator size = 1 (e.g. PETSC_COMM_SELF), i.e. only PetscInfo() calls which print from every rank of PETSC_COMM_WORLD are enabled. By contrast, ~self means that PetscInfo() is enabled only for communicator size > 1 (e.g. PETSC_COMM_WORLD), i.e. those PetscInfo() calls which print from every rank of PETSC_COMM_WORLD are disabled. All classname/self matching is case insensitive. Filename is case sensitive. Example of Usage: $ Mat A; $ PetscInt alpha; $ ... $ PetscInfo1(A,"Matrix uses parameter alpha=%D\n",alpha); Options Examples: Each call of the form $ PetscInfo(obj, msg); $ PetscInfo1(obj, msg, arg1); $ PetscInfo2(obj, msg, arg1, arg2); is evaluated as follows. $ -info or -info :: prints msg to PETSC_STDOUT, for any obj regardless class or communicator $ -info :mat:self prints msg to PETSC_STDOUT only if class of obj is Mat, and its communicator has size = 1 $ -info myInfoFileName:~vec:~self prints msg to file named myInfoFileName, only if the obj's class is NULL or other than Vec, and obj's communicator has size > 1 $ -info :sys prints to PETSC_STDOUT only if obj is NULL Note that $ -info :sys:~self deactivates all info messages because sys means obj = NULL which implies PETSC_COMM_SELF but ~self filters out everything on PETSC_COMM_SELF. Fortran Note: This function does not take the obj argument, there is only the PetscInfo() version, not PetscInfo1() etc. Level: intermediate .seealso: PetscInfoAllow(), PetscInfoSetFromOptions() M*/ PetscErrorCode PetscInfo_Private(const char func[],PetscObject obj, const char message[], ...) { va_list Argp; PetscMPIInt rank = 0,urank,size = 1; PetscClassId classid; PetscBool enabled = PETSC_FALSE, oldflag; char string[8*1024]; PetscErrorCode ierr; size_t fullLength,len; int err; PetscFunctionBegin; if (obj) PetscValidHeader(obj,2); classid = obj ? obj->classid : PETSC_SMALLEST_CLASSID; ierr = PetscInfoEnabled(classid, &enabled);CHKERRQ(ierr); if (!enabled) PetscFunctionReturn(0); PetscValidCharPointer(message,3); if (obj) { ierr = MPI_Comm_rank(obj->comm, &rank);CHKERRMPI(ierr); ierr = MPI_Comm_size(obj->comm, &size);CHKERRMPI(ierr); } /* rank > 0 always jumps out */ if (rank) PetscFunctionReturn(0); if (!PetscInfoCommFilter && (size < 2)) { /* If no self printing is allowed, and size too small get out */ PetscFunctionReturn(0); } else if ((PetscInfoCommFilter == PETSC_INFO_COMM_ONLY_SELF) && (size > 1)) { /* If ONLY self printing, and size too big, get out */ PetscFunctionReturn(0); } /* Mute info messages within this function */ oldflag = PetscLogPrintInfo; PetscLogPrintInfo = PETSC_FALSE; ierr = MPI_Comm_rank(MPI_COMM_WORLD, &urank);CHKERRMPI(ierr); va_start(Argp, message); sprintf(string, "[%d] %s(): ",urank,func); ierr = PetscStrlen(string, &len);CHKERRQ(ierr); ierr = PetscVSNPrintf(string+len, 8*1024-len,message,&fullLength, Argp);CHKERRQ(ierr); ierr = PetscFPrintf(PETSC_COMM_SELF,PetscInfoFile, "%s", string);CHKERRQ(ierr); err = fflush(PetscInfoFile); if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); if (petsc_history) { va_start(Argp, message); ierr = (*PetscVFPrintf)(petsc_history, message, Argp);CHKERRQ(ierr); } va_end(Argp); PetscLogPrintInfo = oldflag; PetscFunctionReturn(0); }