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