xref: /petsc/src/sys/info/verboseinfo.c (revision be37439ebbbdb2f81c3420c175a94aa72e59929c)
1 /*
2       PetscInfo() is contained in a different file from the other profiling to
3    allow it to be replaced at link time by an alternative routine.
4 */
5 #include <petsc/private/petscimpl.h> /*I    "petscsys.h"   I*/
6 
7 /*
8   The next set of variables determine which, if any, PetscInfo() calls are used.
9   If PetscLogPrintInfo is false, no info messages are printed.
10 
11   If PetscInfoFlags[OBJECT_CLASSID - PETSC_SMALLEST_CLASSID] is zero, no messages related
12   to that object are printed. OBJECT_CLASSID is, for example, MAT_CLASSID.
13   Note for developers: the PetscInfoFlags array is currently 160 entries large, to ensure headroom. Perhaps it is worth
14   dynamically allocating this array intelligently rather than just some big number.
15 
16   PetscInfoFilename determines where PetscInfo() output is piped.
17   PetscInfoClassnames holds a char array of classes which are filtered out/for in PetscInfo() calls.
18 */
19 const char *const        PetscInfoCommFlags[]   = {"all", "no_self", "only_self", "PetscInfoCommFlag", "PETSC_INFO_COMM_", NULL};
20 static PetscBool         PetscInfoClassesLocked = PETSC_FALSE, PetscInfoInvertClasses = PETSC_FALSE, PetscInfoClassesSet = PETSC_FALSE;
21 static char            **PetscInfoClassnames = NULL;
22 static char             *PetscInfoFilename   = NULL;
23 static PetscInt          PetscInfoNumClasses = -1;
24 static PetscInfoCommFlag PetscInfoCommFilter = PETSC_INFO_COMM_ALL;
25 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,
26                                                 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,
27                                                 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};
28 static char             *PetscInfoNames[PETSC_STATIC_ARRAY_LENGTH(PetscInfoFlags)] = {NULL};
29 PetscBool                PetscLogPrintInfo                                         = PETSC_FALSE;
30 FILE                    *PetscInfoFile                                             = NULL;
31 
32 /*@
33   PetscInfoEnabled - Checks whether a given `PetscClassid` is allowed to print using `PetscInfo()`
34 
35   Not Collective
36 
37   Input Parameter:
38 . classid - `PetscClassid` retrieved from a `PetscObject` e.g. `VEC_CLASSID`
39 
40   Output Parameter:
41 . enabled - `PetscBool` indicating whether this classid is allowed to print
42 
43   Level: advanced
44 
45   Note:
46   Use `PETSC_SMALLEST_CLASSID` to check if "sys" `PetscInfo()` calls are enabled. When PETSc is configured with debugging
47   support this function checks if classid >= `PETSC_SMALLEST_CLASSID`, otherwise it assumes valid classid.
48 
49 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoGetInfo()`, `PetscObjectGetClassid()`
50 @*/
PetscInfoEnabled(PetscClassId classid,PetscBool * enabled)51 PetscErrorCode PetscInfoEnabled(PetscClassId classid, PetscBool *enabled)
52 {
53   PetscFunctionBegin;
54   PetscAssertPointer(enabled, 2);
55   PetscCheck(classid >= PETSC_SMALLEST_CLASSID, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Classid (current: %d) must be equal to or greater than PETSC_SMALLEST_CLASSID", classid);
56   *enabled = (PetscBool)(PetscLogPrintInfo && PetscInfoFlags[classid - PETSC_SMALLEST_CLASSID]);
57   PetscFunctionReturn(PETSC_SUCCESS);
58 }
59 
60 /*@
61   PetscInfoAllow - Enables/disables `PetscInfo()` messages
62 
63   Not Collective
64 
65   Input Parameter:
66 . flag - `PETSC_TRUE` or `PETSC_FALSE`
67 
68   Level: advanced
69 
70 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoEnabled()`, `PetscInfoGetInfo()`, `PetscInfoSetFromOptions()`
71 @*/
PetscInfoAllow(PetscBool flag)72 PetscErrorCode PetscInfoAllow(PetscBool flag)
73 {
74   PetscFunctionBegin;
75   PetscLogPrintInfo = flag;
76   PetscFunctionReturn(PETSC_SUCCESS);
77 }
78 
79 /*@
80   PetscInfoSetFile - Sets the printing destination for all `PetscInfo()` calls
81 
82   Not Collective
83 
84   Input Parameters:
85 + filename - Name of the file where `PetscInfo()` will print to, use `NULL` to write to `PETSC_STDOUT`.
86 - mode     - Write mode passed to `PetscFOpen()`
87 
88   Level: advanced
89 
90 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoGetFile()`, `PetscInfoSetFromOptions()`, `PetscFOpen()`
91 @*/
PetscInfoSetFile(const char filename[],const char mode[])92 PetscErrorCode PetscInfoSetFile(const char filename[], const char mode[])
93 {
94   PetscFunctionBegin;
95   if (!PetscInfoFile) PetscInfoFile = PETSC_STDOUT;
96   PetscCall(PetscFree(PetscInfoFilename));
97   if (filename) {
98     PetscMPIInt rank;
99     char        fname[PETSC_MAX_PATH_LEN], tname[11];
100 
101     PetscAssertPointer(filename, 1);
102     PetscAssertPointer(mode, 2);
103     PetscCall(PetscFixFilename(filename, fname));
104     PetscCall(PetscStrallocpy(fname, &PetscInfoFilename));
105     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
106     PetscCall(PetscSNPrintf(tname, PETSC_STATIC_ARRAY_LENGTH(tname), ".%d", rank));
107     PetscCall(PetscStrlcat(fname, tname, PETSC_STATIC_ARRAY_LENGTH(fname)));
108     {
109       const PetscBool oldflag = PetscLogPrintInfo;
110 
111       PetscLogPrintInfo = PETSC_FALSE;
112       PetscCall(PetscFOpen(PETSC_COMM_SELF, fname, mode, &PetscInfoFile));
113       PetscLogPrintInfo = oldflag;
114       /*
115         PetscFOpen will write to PETSC_STDOUT and not PetscInfoFile here, so we disable the
116         PetscInfo call inside it, and call it afterwards so that it actually writes to file
117       */
118     }
119     PetscCall(PetscInfo(NULL, "Opened PetscInfo file %s\n", fname));
120   }
121   PetscFunctionReturn(PETSC_SUCCESS);
122 }
123 
124 /*@C
125   PetscInfoGetFile - Gets the `filename` and `FILE` pointer of the file where `PetscInfo()` prints to
126 
127   Not Collective; No Fortran Support
128 
129   Output Parameters:
130 + filename - The name of the output file
131 - InfoFile - The `FILE` pointer for the output file
132 
133   Level: advanced
134 
135   Note:
136   This routine allocates and copies the `filename` so that the `filename` survives `PetscInfoDestroy()`. The user is
137   therefore responsible for freeing the allocated `filename` pointer with `PetscFree()`
138 
139 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoSetFile()`, `PetscInfoSetFromOptions()`, `PetscInfoDestroy()`
140 @*/
PetscInfoGetFile(char * filename[],FILE ** InfoFile)141 PetscErrorCode PetscInfoGetFile(char *filename[], FILE **InfoFile)
142 {
143   PetscFunctionBegin;
144   PetscAssertPointer(filename, 1);
145   PetscAssertPointer(InfoFile, 2);
146   PetscCall(PetscStrallocpy(PetscInfoFilename, filename));
147   *InfoFile = PetscInfoFile;
148   PetscFunctionReturn(PETSC_SUCCESS);
149 }
150 
151 /*@C
152   PetscInfoSetClasses - Sets the classes which `PetscInfo()` is filtered for/against
153 
154   Not Collective; No Fortran Support
155 
156   Input Parameters:
157 + exclude    - Whether or not to invert the filter, i.e. if exclude is true, `PetscInfo()` will print from every class that
158     is NOT one of the classes specified
159 . n          - Number of classes to filter for (size of `classnames`)
160 - classnames - String array containing the names of classes to filter for, e.g. "vec"
161 
162   Level: developer
163 
164   Notes:
165   This function CANNOT be called after `PetscInfoGetClass()` or `PetscInfoProcessClass()` has been called, unless the user calls `PetscInfoDestroy()` first.
166 
167   Names in the `classnames` list should correspond to the names returned by `PetscObjectGetClassName()`.
168 
169   This function only sets the list of class names.
170   The actual filtering is deferred to `PetscInfoProcessClass()`, except of sys which is processed right away.
171   The reason for this is that we need to set the list of included/excluded classes before their classids are known.
172   Typically the classid is assigned and `PetscInfoProcessClass()` called in <Class>InitializePackage() (e.g. `VecInitializePackage()`).
173 
174 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoGetClass()`, `PetscInfoProcessClass()`, `PetscInfoSetFromOptions()`, `PetscStrToArray()`, `PetscObjectGetName()`
175 @*/
PetscInfoSetClasses(PetscBool exclude,PetscInt n,const char * const * classnames)176 PetscErrorCode PetscInfoSetClasses(PetscBool exclude, PetscInt n, const char *const *classnames)
177 {
178   PetscFunctionBegin;
179   PetscCheck(!PetscInfoClassesLocked, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Trying to modify PetscInfo() configuration after it has been locked to a read-only state. Usually, this is an *error*! To re-enable modification, you must reset PetscInfo() by calling PetscInfoDestroy() first");
180   PetscCall(PetscStrNArrayDestroy(PetscInfoNumClasses, &PetscInfoClassnames));
181   PetscCall(PetscStrNArrayallocpy(n, classnames, &PetscInfoClassnames));
182   PetscInfoNumClasses    = n;
183   PetscInfoInvertClasses = exclude;
184   /* Process sys class right away */
185   {
186     const PetscClassId id = PETSC_SMALLEST_CLASSID;
187 
188     PetscCall(PetscInfoProcessClass("sys", 1, &id));
189   }
190   PetscInfoClassesSet = PETSC_TRUE;
191   PetscFunctionReturn(PETSC_SUCCESS);
192 }
193 
194 /*@
195   PetscInfoGetClass - Indicates whether the provided `classname` is marked as a filter in `PetscInfo()` as set by `PetscInfoSetClasses()`
196 
197   Not Collective
198 
199   Input Parameter:
200 . classname - Name of the class to search for
201 
202   Output Parameter:
203 . found - `PetscBool` indicating whether the classname was found
204 
205   Level: developer
206 
207   Note:
208   Use `PetscObjectGetName()` to retrieve an appropriate classname
209 
210 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoSetClasses()`, `PetscInfoSetFromOptions()`, `PetscObjectGetName()`
211 @*/
PetscInfoGetClass(const char classname[],PetscBool * found)212 PetscErrorCode PetscInfoGetClass(const char classname[], PetscBool *found)
213 {
214   PetscInt unused;
215 
216   PetscFunctionBegin;
217   PetscAssertPointer(classname, 1);
218   PetscAssertPointer(found, 2);
219   PetscCall(PetscEListFind(PetscInfoNumClasses, (const char *const *)PetscInfoClassnames, classname ? classname : "sys", &unused, found));
220   PetscInfoClassesLocked = PETSC_TRUE;
221   PetscFunctionReturn(PETSC_SUCCESS);
222 }
223 
224 /*@
225   PetscInfoGetInfo - Returns the current state of several flags for `PetscInfo()`
226 
227   Not Collective
228 
229   Output Parameters:
230 + infoEnabled  - `PETSC_TRUE` if `PetscInfoAllow`(`PETSC_TRUE`) has been called
231 . classesSet   - `PETSC_TRUE` if the list of classes to filter for has been set
232 . exclude      - `PETSC_TRUE` if the class filtering for `PetscInfo()` is inverted
233 . locked       - `PETSC_TRUE` if the list of classes to filter for has been locked
234 - commSelfFlag - Enum indicating whether `PetscInfo()` will print for communicators of size 1, any size != 1, or all
235     communicators
236 
237   Level: developer
238 
239   Note:
240   Initially commSelfFlag = `PETSC_INFO_COMM_ALL`
241 
242 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFilterCommSelf`, `PetscInfoSetFromOptions()`
243 @*/
PetscInfoGetInfo(PetscBool * infoEnabled,PetscBool * classesSet,PetscBool * exclude,PetscBool * locked,PetscInfoCommFlag * commSelfFlag)244 PetscErrorCode PetscInfoGetInfo(PetscBool *infoEnabled, PetscBool *classesSet, PetscBool *exclude, PetscBool *locked, PetscInfoCommFlag *commSelfFlag)
245 {
246   PetscFunctionBegin;
247   if (infoEnabled) PetscAssertPointer(infoEnabled, 1);
248   if (classesSet) PetscAssertPointer(classesSet, 2);
249   if (exclude) PetscAssertPointer(exclude, 3);
250   if (locked) PetscAssertPointer(locked, 4);
251   if (commSelfFlag) PetscAssertPointer(commSelfFlag, 5);
252   if (infoEnabled) *infoEnabled = PetscLogPrintInfo;
253   if (classesSet) *classesSet = PetscInfoClassesSet;
254   if (exclude) *exclude = PetscInfoInvertClasses;
255   if (locked) *locked = PetscInfoClassesLocked;
256   if (commSelfFlag) *commSelfFlag = PetscInfoCommFilter;
257   PetscFunctionReturn(PETSC_SUCCESS);
258 }
259 
260 /*@
261   PetscInfoProcessClass - Activates or deactivates a class based on the filtering status of `PetscInfo()`
262 
263   Not Collective
264 
265   Input Parameters:
266 + classname  - Name of the class to activate/deactivate `PetscInfo()` for
267 . numClassID - Number of entries in `classIDs`
268 - classIDs   - Array containing all of the `PetscClassId`s associated with `classname`
269 
270   Options Database Key:
271 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, see `PetscInfo()`.
272 
273   Level: developer
274 
275 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoActivateClass()`, `PetscInfoDeactivateClass()`, `PetscInfoSetFromOptions()`
276 @*/
PetscInfoProcessClass(const char classname[],PetscInt numClassID,const PetscClassId classIDs[])277 PetscErrorCode PetscInfoProcessClass(const char classname[], PetscInt numClassID, const PetscClassId classIDs[])
278 {
279   PetscBool enabled, exclude, found, opt;
280   char      logList[256];
281 
282   PetscFunctionBegin;
283   PetscAssertPointer(classname, 1);
284   PetscAssert(numClassID > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of classids %" PetscInt_FMT " <= 0", numClassID);
285   if (numClassID) PetscAssertPointer(classIDs, 3);
286   PetscCall(PetscInfoGetInfo(&enabled, NULL, &exclude, NULL, NULL));
287   PetscCall(PetscOptionsDeprecated_Private(NULL, "-info_exclude", NULL, "3.13", "Use ~ with -info to indicate classes to exclude"));
288   PetscCall(PetscOptionsGetString(NULL, NULL, "-info_exclude", logList, sizeof(logList), &opt));
289   if (opt) {
290     PetscBool pkg;
291 
292     PetscCall(PetscStrInList(classname, logList, ',', &pkg));
293     if (pkg) {
294       for (PetscInt i = 0; i < numClassID; ++i) PetscCall(PetscInfoDeactivateClass(classIDs[i]));
295     }
296   }
297   PetscCheck(PETSC_LARGEST_CLASSID - PETSC_SMALLEST_CLASSID < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(PetscInfoNames), PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscInfoNames array is too small for %s, need %d not %d", classname, PETSC_LARGEST_CLASSID - PETSC_SMALLEST_CLASSID + 1, (int)PETSC_STATIC_ARRAY_LENGTH(PetscInfoNames));
298   for (PetscInt i = 0; i < numClassID; ++i) {
299     const PetscClassId idx = classIDs[i] - PETSC_SMALLEST_CLASSID;
300 
301     PetscCall(PetscFree(PetscInfoNames[idx]));
302     PetscCall(PetscStrallocpy(classname, PetscInfoNames + idx));
303   }
304   PetscCall(PetscInfoGetClass(classname, &found));
305   if ((found && exclude) || (!found && !exclude)) {
306     if (PetscInfoNumClasses > 0) {
307       /* Check if -info was called empty */
308       for (PetscInt i = 0; i < numClassID; ++i) PetscCall(PetscInfoDeactivateClass(classIDs[i]));
309     }
310   } else {
311     for (PetscInt i = 0; i < numClassID; ++i) PetscCall(PetscInfoActivateClass(classIDs[i]));
312   }
313   PetscFunctionReturn(PETSC_SUCCESS);
314 }
315 
316 /*@
317   PetscInfoSetFilterCommSelf - Sets `PetscInfoCommFlag` enum to determine communicator filtering for `PetscInfo()`
318 
319   Not Collective
320 
321   Input Parameter:
322 . commSelfFlag - Enum value indicating method with which to filter `PetscInfo()` based on the size of the communicator of the object calling `PetscInfo()`
323 
324   Options Database Key:
325 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
326 
327   Level: advanced
328 
329 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoGetInfo()`
330 @*/
PetscInfoSetFilterCommSelf(PetscInfoCommFlag commSelfFlag)331 PetscErrorCode PetscInfoSetFilterCommSelf(PetscInfoCommFlag commSelfFlag)
332 {
333   PetscFunctionBegin;
334   PetscInfoCommFilter = commSelfFlag;
335   PetscFunctionReturn(PETSC_SUCCESS);
336 }
337 
338 /*@
339   PetscInfoSetFromOptions - Configure `PetscInfo()` using command line options, enabling or disabling various calls to `PetscInfo()`
340 
341   Not Collective
342 
343   Input Parameter:
344 . options - Options database, use `NULL` for default global database
345 
346   Options Database Key:
347 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
348 
349   Level: advanced
350 
351   Note:
352   This function is called automatically during `PetscInitialize()` so users usually do not need to call it themselves.
353 
354 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFile()`, `PetscInfoSetClasses()`, `PetscInfoSetFilterCommSelf()`, `PetscInfoDestroy()`
355 @*/
PetscInfoSetFromOptions(PetscOptions options)356 PetscErrorCode PetscInfoSetFromOptions(PetscOptions options)
357 {
358   char      optstring[PETSC_MAX_PATH_LEN];
359   PetscBool set;
360 
361   PetscFunctionBegin;
362   PetscCall(PetscOptionsGetString(options, NULL, "-info", optstring, PETSC_STATIC_ARRAY_LENGTH(optstring), &set));
363   if (set) {
364     size_t            size_loc0_, size_loc1_, size_loc2_;
365     char             *loc0_ = NULL, *loc1_ = NULL, *loc2_ = NULL;
366     char            **loc1_array  = NULL;
367     PetscBool         loc1_invert = PETSC_FALSE, loc2_invert = PETSC_FALSE;
368     int               nLoc1_       = 0;
369     PetscInfoCommFlag commSelfFlag = PETSC_INFO_COMM_ALL;
370 
371     PetscInfoClassesSet = PETSC_TRUE;
372     PetscCall(PetscInfoAllow(PETSC_TRUE));
373     PetscCall(PetscStrallocpy(optstring, &loc0_));
374     PetscCall(PetscStrchr(loc0_, ':', &loc1_));
375     if (loc1_) {
376       *loc1_++ = 0;
377       if (*loc1_ == '~') {
378         loc1_invert = PETSC_TRUE;
379         ++loc1_;
380       }
381       PetscCall(PetscStrchr(loc1_, ':', &loc2_));
382     }
383     if (loc2_) {
384       *loc2_++ = 0;
385       if (*loc2_ == '~') {
386         loc2_invert = PETSC_TRUE;
387         ++loc2_;
388       }
389     }
390     PetscCall(PetscStrlen(loc0_, &size_loc0_));
391     PetscCall(PetscStrlen(loc1_, &size_loc1_));
392     PetscCall(PetscStrlen(loc2_, &size_loc2_));
393     if (size_loc1_) {
394       PetscCall(PetscStrtolower(loc1_));
395       PetscCall(PetscStrToArray(loc1_, ',', &nLoc1_, &loc1_array));
396     }
397     if (size_loc2_) {
398       PetscBool foundSelf;
399 
400       PetscCall(PetscStrtolower(loc2_));
401       PetscCall(PetscStrcmp("self", loc2_, &foundSelf));
402       if (foundSelf) commSelfFlag = loc2_invert ? PETSC_INFO_COMM_NO_SELF : PETSC_INFO_COMM_ONLY_SELF;
403     }
404     PetscCall(PetscInfoSetFile(size_loc0_ ? loc0_ : NULL, "w"));
405     PetscCall(PetscInfoSetClasses(loc1_invert, nLoc1_, (const char *const *)loc1_array));
406     PetscCall(PetscInfoSetFilterCommSelf(commSelfFlag));
407     PetscCall(PetscStrToArrayDestroy(nLoc1_, loc1_array));
408     PetscCall(PetscFree(loc0_));
409   }
410   PetscFunctionReturn(PETSC_SUCCESS);
411 }
412 
413 /*@
414   PetscInfoDestroy - Destroys and resets internal `PetscInfo()` data structures.
415 
416   Not Collective
417 
418   Level: developer
419 
420   Notes:
421   This is automatically called in `PetscFinalize()`. Useful for changing filters mid-program, or culling subsequent
422   `PetscInfo()` calls down the line.
423 
424   Users calling this routine midway through a program should note that `PetscInfoDestroy()`
425   constitutes a full reset of `PetscInfo()`. It flushes, then closes, the current info file,
426   re-enables all classes, and resets all internal state. Finally -- and perhaps crucially -- it
427   disables `PetscInfo()` as-if-by `PetscInfoAllow(PETSC_FALSE)`.
428 
429 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoSetFromOptions()`
430 @*/
PetscInfoDestroy(void)431 PetscErrorCode PetscInfoDestroy(void)
432 {
433   PetscFunctionBegin;
434   PetscCall(PetscInfoAllow(PETSC_FALSE));
435   PetscCall(PetscStrNArrayDestroy(PetscInfoNumClasses, &PetscInfoClassnames));
436   if (PetscInfoFile) PetscCall(PetscFFlush(PetscInfoFile));
437   if (PetscInfoFilename) {
438     PetscAssert(PetscInfoFile, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Have non-null PetscInfo file '%s', but corresponding FILE handle is null!", PetscInfoFilename);
439     PetscCall(PetscFree(PetscInfoFilename));
440     PetscCall(PetscFClose(PETSC_COMM_SELF, PetscInfoFile));
441   }
442   PetscAssert(PETSC_STATIC_ARRAY_LENGTH(PetscInfoFlags) == PETSC_STATIC_ARRAY_LENGTH(PetscInfoNames), PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscInfoFlags and PetscInfoNames must be the same size");
443   for (size_t i = 0; i < PETSC_STATIC_ARRAY_LENGTH(PetscInfoFlags); ++i) {
444     PetscInfoFlags[i] = 1;
445     PetscCall(PetscFree(PetscInfoNames[i]));
446   }
447 
448   PetscInfoFile          = NULL;
449   PetscInfoClassesLocked = PETSC_FALSE;
450   PetscInfoInvertClasses = PETSC_FALSE;
451   PetscInfoClassesSet    = PETSC_FALSE;
452   PetscInfoNumClasses    = -1;
453   PetscInfoCommFilter    = PETSC_INFO_COMM_ALL;
454   PetscFunctionReturn(PETSC_SUCCESS);
455 }
456 
PetscInfoSetClassActivation_Private(PetscClassId classid,int value)457 static PetscErrorCode PetscInfoSetClassActivation_Private(PetscClassId classid, int value)
458 {
459   PetscFunctionBegin;
460   if (!classid) classid = PETSC_SMALLEST_CLASSID;
461   PetscInfoFlags[classid - PETSC_SMALLEST_CLASSID] = value;
462   PetscFunctionReturn(PETSC_SUCCESS);
463 }
464 
465 /*@
466   PetscInfoDeactivateClass - Deactivates `PetscInfo()` messages for a PETSc object class.
467 
468   Not Collective
469 
470   Input Parameter:
471 . classid - The object class,  e.g., `MAT_CLASSID`, `SNES_CLASSID`, etc.
472 
473   Options Database Key:
474 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
475 
476   Level: developer
477 
478   Note:
479   One can pass 0 to deactivate all messages that are not associated with an object.
480 
481 .seealso: [](sec_PetscInfo), `PetscInfoActivateClass()`, `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFromOptions()`
482 @*/
PetscInfoDeactivateClass(PetscClassId classid)483 PetscErrorCode PetscInfoDeactivateClass(PetscClassId classid)
484 {
485   PetscFunctionBegin;
486   PetscCall(PetscInfoSetClassActivation_Private(classid, 0));
487   PetscFunctionReturn(PETSC_SUCCESS);
488 }
489 
490 /*@
491   PetscInfoActivateClass - Activates `PetscInfo()` messages for a PETSc object class.
492 
493   Not Collective
494 
495   Input Parameter:
496 . classid - The object class, e.g., `MAT_CLASSID`, `SNES_CLASSID`, etc.
497 
498   Options Database Key:
499 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
500 
501   Level: developer
502 
503   Note:
504   One can pass 0 to activate all messages that are not associated with an object.
505 
506 .seealso: [](sec_PetscInfo), `PetscInfoDeactivateClass()`, `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFromOptions()`
507 @*/
PetscInfoActivateClass(PetscClassId classid)508 PetscErrorCode PetscInfoActivateClass(PetscClassId classid)
509 {
510   PetscFunctionBegin;
511   PetscCall(PetscInfoSetClassActivation_Private(classid, 1));
512   PetscFunctionReturn(PETSC_SUCCESS);
513 }
514 
515 /*
516    If the option -history was used, then all printed PetscInfo()
517   messages are also printed to the history file, called by default
518   .petschistory in ones home directory.
519 */
520 PETSC_INTERN FILE          *petsc_history;
521 PETSC_INTERN PetscErrorCode PetscVFPrintf_Internal(FILE *, const char[], ...);
522 
523 /*MC
524   PetscInfo - Logs informative data
525 
526   Synopsis:
527   #include <petsclog.h>
528   PetscErrorCode PetscInfo(PetscObject obj, const char message[], ...)
529 
530   Collective
531 
532   Input Parameters:
533 + obj     - object most closely associated with the logging statement or `NULL`
534 - message - logging message using standard "printf" format
535 
536   Options Database Key:
537 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed
538 
539   Level: intermediate
540 
541   Notes:
542   `PetscInfo()` prints only from the first processor in the communicator of `obj`.
543   If `obj` is `NULL`, the `PETSC_COMM_SELF` communicator is used, i.e. every rank of `PETSC_COMM_WORLD` prints the message.
544 
545   The optional <list,of,classnames> is a comma separated list of enabled classes, e.g. `vec,mat,ksp`.
546   If this list is not specified, all classes are enabled.
547   Prepending the list with ~ means inverted selection, i.e. all classes except the listed are enabled.
548   A special classname `sys` relates to `PetscInfo()` with `obj` being `NULL`.
549 
550   The optional keyword `self` specifies that `PetscInfo()` is enabled only for a communicator size of 1 (e.g. `PETSC_COMM_SELF`).
551   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.
552 
553   All classname/self matching is case insensitive. Filename is case sensitive.
554 
555   Example of Usage:
556 .vb
557      Mat A;
558      PetscInt alpha;
559      ...
560      PetscInfo(A,"Matrix uses parameter alpha=%" PetscInt_FMT "\n",alpha);
561 .ve
562 
563   Examples using Options:
564   Each call of the form
565 .vb
566      PetscInfo(obj, msg);
567      PetscInfo(obj, msg, arg1);
568      PetscInfo(obj, msg, arg1, arg2);
569 .ve
570   is evaluated as follows.
571 .vb
572     -info or -info :: prints `msg` to `PETSC_STDOUT`, for any PETSc `obj` regardless class or communicator
573     -info :mat:self prints `msg` to `PETSC_STDOUT` only if class of `obj` is `Mat`, and its communicator has size = 1
574     -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
575     -info :sys prints to `PETSC_STDOUT` only if `obj` is `NULL`
576     -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`.
577 .ve
578 
579   Fortran Notes:
580   This function does not take the `obj` argument, there is only the `PetscInfo()`
581   version, not `PetscInfo()` etc.
582 
583 .seealso: [](sec_PetscInfo), `PetscInfoAllow()`, `PetscInfoSetFromOptions()`, `PetscInfoEnabled()`, `PetscInfoSetFile()`, `PetscInfoGetFile()`, `PetscInfoSetClasses()`,
584           `PetscInfoGetClass()`, `PetscInfoGetInfo()`, `PetscInfoProcessClass()`, `PetscInfoSetFilterCommSelf()`, `PetscInfoDestroy()`, `PetscInfoDeactivateClass()`,
585           `PetscInfoActivateClass()`
586 M*/
PetscInfo_Private(const char func[],PetscObject obj,const char message[],...)587 PetscErrorCode PetscInfo_Private(const char func[], PetscObject obj, const char message[], ...)
588 {
589   PetscClassId classid = PETSC_SMALLEST_CLASSID;
590   PetscBool    enabled = PETSC_FALSE;
591   MPI_Comm     comm    = MPI_COMM_NULL;
592   PetscMPIInt  rank    = 0;
593   const char  *otype   = NULL;
594 
595   PetscFunctionBegin;
596   if (obj) {
597     PetscValidHeader(obj, 2);
598     classid = obj->classid;
599   }
600   PetscAssertPointer(message, 3);
601   PetscCall(PetscInfoEnabled(classid, &enabled));
602   if (!enabled) PetscFunctionReturn(PETSC_SUCCESS);
603   if (obj) {
604     PetscCall(PetscObjectGetComm(obj, &comm));
605     PetscCall(PetscObjectGetType(obj, &otype));
606     PetscCallMPI(MPI_Comm_rank(comm, &rank));
607   }
608   /* rank > 0 always jumps out */
609   if (rank) PetscFunctionReturn(PETSC_SUCCESS);
610   else {
611     PetscMPIInt size = 1;
612 
613     if (comm != MPI_COMM_NULL) PetscCallMPI(MPI_Comm_size(comm, &size));
614     /* If no self printing is allowed, and size too small, get out */
615     if ((PetscInfoCommFilter == PETSC_INFO_COMM_NO_SELF) && (size < 2)) PetscFunctionReturn(PETSC_SUCCESS);
616     /* If ONLY self printing, and size too big, get out */
617     if ((PetscInfoCommFilter == PETSC_INFO_COMM_ONLY_SELF) && (size > 1)) PetscFunctionReturn(PETSC_SUCCESS);
618   }
619   /* Mute info messages within this function */
620   {
621     const PetscBool oldflag = PetscLogPrintInfo;
622     va_list         Argp;
623     PetscMPIInt     urank;
624     char            string[8 * 1024];
625     size_t          fullLength, len;
626 
627     PetscLogPrintInfo = PETSC_FALSE;
628     PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &urank));
629     if (otype) {
630       PetscCall(PetscSNPrintf(string, PETSC_STATIC_ARRAY_LENGTH(string), "[%d] <%s:%s> %s(): ", urank, PetscInfoNames[classid - PETSC_SMALLEST_CLASSID], otype, func));
631     } else {
632       PetscCall(PetscSNPrintf(string, PETSC_STATIC_ARRAY_LENGTH(string), "[%d] <%s> %s(): ", urank, PetscInfoNames[classid - PETSC_SMALLEST_CLASSID], func));
633     }
634     PetscCall(PetscStrlen(string, &len));
635     va_start(Argp, message);
636     PetscCall(PetscVSNPrintf(string + len, 8 * 1024 - len, message, &fullLength, Argp));
637     va_end(Argp);
638     PetscCall(PetscVFPrintf_Internal(PetscInfoFile, "%s", string));
639     PetscCall(PetscFFlush(PetscInfoFile));
640     if (petsc_history) {
641       va_start(Argp, message);
642       PetscCall((*PetscVFPrintf)(petsc_history, message, Argp));
643       va_end(Argp);
644     }
645     PetscLogPrintInfo = oldflag;
646   }
647   PetscFunctionReturn(PETSC_SUCCESS);
648 }
649