xref: /petsc/src/sys/info/verboseinfo.c (revision e4094ef18e7e53fda86cf35f3a47fda48a8e77d8)
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 `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 @*/
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: [](sec_PetscInfo), `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: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoGetFile()`, `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: [](sec_PetscInfo), `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: [](sec_PetscInfo), `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: [](sec_PetscInfo), `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 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: [](sec_PetscInfo), `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: [](sec_PetscInfo), `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: [](sec_PetscInfo), `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: [](sec_PetscInfo), `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: [](sec_PetscInfo), `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: [](sec_PetscInfo), `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: [](sec_PetscInfo), `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
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   Examples using Options:
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 PETSc `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 
585   Fortran Notes:
586   This function does not take the `obj` argument, there is only the `PetscInfo()`
587   version, not `PetscInfo()` etc.
588 
589 .seealso: [](sec_PetscInfo), `PetscInfoAllow()`, `PetscInfoSetFromOptions()`, `PetscInfoEnabled()`, `PetscInfoSetFile()`, `PetscInfoGetFile()`, `PetscInfoSetClasses()`,
590           `PetscInfoGetClass()`, `PetscInfoGetInfo()`, `PetscInfoProcessClass()`, `PetscInfoSetFilterCommSelf()`, `PetscInfoDestroy()`, `PetscInfoDeactivateClass()`,
591           `PetscInfoActivateClass()`
592 M*/
593 PetscErrorCode PetscInfo_Private(const char func[], PetscObject obj, const char message[], ...)
594 {
595   PetscClassId classid = PETSC_SMALLEST_CLASSID;
596   PetscBool    enabled = PETSC_FALSE;
597   MPI_Comm     comm    = PETSC_COMM_SELF;
598   PetscMPIInt  rank;
599   const char  *otype = NULL;
600 
601   PetscFunctionBegin;
602   if (obj) {
603     PetscValidHeader(obj, 2);
604     classid = obj->classid;
605   }
606   PetscValidCharPointer(message, 3);
607   PetscCall(PetscInfoEnabled(classid, &enabled));
608   if (!enabled) PetscFunctionReturn(PETSC_SUCCESS);
609   if (obj) {
610     PetscCall(PetscObjectGetComm(obj, &comm));
611     PetscCall(PetscObjectGetType(obj, &otype));
612   }
613   PetscCallMPI(MPI_Comm_rank(comm, &rank));
614   /* rank > 0 always jumps out */
615   if (rank) PetscFunctionReturn(PETSC_SUCCESS);
616   else {
617     PetscMPIInt size;
618 
619     PetscCallMPI(MPI_Comm_size(comm, &size));
620     /* If no self printing is allowed, and size too small, get out */
621     if ((PetscInfoCommFilter == PETSC_INFO_COMM_NO_SELF) && (size < 2)) PetscFunctionReturn(PETSC_SUCCESS);
622     /* If ONLY self printing, and size too big, get out */
623     if ((PetscInfoCommFilter == PETSC_INFO_COMM_ONLY_SELF) && (size > 1)) PetscFunctionReturn(PETSC_SUCCESS);
624   }
625   /* Mute info messages within this function */
626   {
627     const PetscBool oldflag = PetscLogPrintInfo;
628     va_list         Argp;
629     PetscMPIInt     urank;
630     char            string[8 * 1024];
631     size_t          fullLength, len;
632 
633     PetscLogPrintInfo = PETSC_FALSE;
634     PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &urank));
635     if (otype) {
636       PetscCall(PetscSNPrintf(string, PETSC_STATIC_ARRAY_LENGTH(string), "[%d] <%s:%s> %s(): ", urank, PetscInfoNames[classid - PETSC_SMALLEST_CLASSID], otype, func));
637     } else {
638       PetscCall(PetscSNPrintf(string, PETSC_STATIC_ARRAY_LENGTH(string), "[%d] <%s> %s(): ", urank, PetscInfoNames[classid - PETSC_SMALLEST_CLASSID], func));
639     }
640     PetscCall(PetscStrlen(string, &len));
641     va_start(Argp, message);
642     PetscCall(PetscVSNPrintf(string + len, 8 * 1024 - len, message, &fullLength, Argp));
643     va_end(Argp);
644     PetscCall(PetscFPrintf(PETSC_COMM_SELF, PetscInfoFile, "%s", string));
645     PetscCall(PetscFFlush(PetscInfoFile));
646     if (petsc_history) {
647       va_start(Argp, message);
648       PetscCall((*PetscVFPrintf)(petsc_history, message, Argp));
649       va_end(Argp);
650     }
651     PetscLogPrintInfo = oldflag;
652   }
653   PetscFunctionReturn(PETSC_SUCCESS);
654 }
655