xref: /petsc/src/sys/info/verboseinfo.c (revision d9acb416d05abeed0a33bde3a81aeb2ea0364f6a)
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   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 @*/
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     PetscAssertPointer(filename, 1);
105     PetscAssertPointer(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   PetscAssertPointer(filename, 1);
148   PetscAssertPointer(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   PetscAssertPointer(classname, 1);
221   PetscAssertPointer(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) PetscAssertPointer(infoEnabled, 1);
251   if (classesSet) PetscAssertPointer(classesSet, 2);
252   if (exclude) PetscAssertPointer(exclude, 3);
253   if (locked) PetscAssertPointer(locked, 4);
254   if (commSelfFlag) PetscAssertPointer(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   PetscAssertPointer(classname, 1);
287   PetscAssert(numClassID > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of classids %" PetscInt_FMT " <= 0", numClassID);
288   if (numClassID) PetscAssertPointer(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 PETSC_INTERN PetscErrorCode PetscVFPrintf_Internal(FILE *, const char[], ...);
524 
525 /*MC
526   PetscInfo - Logs informative data
527 
528   Synopsis:
529   #include <petsclog.h>
530   PetscErrorCode PetscInfo(PetscObject obj, const char message[], ...)
531 
532   Collective
533 
534   Input Parameters:
535 + obj     - object most closely associated with the logging statement or `NULL`
536 - message - logging message using standard "printf" format
537 
538   Options Database Key:
539 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed
540 
541   Level: intermediate
542 
543   Notes:
544   `PetscInfo()` prints only from the first processor in the communicator of `obj`.
545   If `obj` is `NULL`, the `PETSC_COMM_SELF` communicator is used, i.e. every rank of `PETSC_COMM_WORLD` prints the message.
546 
547   The optional <list,of,classnames> is a comma separated list of enabled classes, e.g. `vec,mat,ksp`.
548   If this list is not specified, all classes are enabled.
549   Prepending the list with ~ means inverted selection, i.e. all classes except the listed are enabled.
550   A special classname `sys` relates to `PetscInfo()` with `obj` being `NULL`.
551 
552   The optional keyword `self` specifies that `PetscInfo()` is enabled only for a communicator size of 1 (e.g. `PETSC_COMM_SELF`).
553   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.
554 
555   All classname/self matching is case insensitive. Filename is case sensitive.
556 
557   Example of Usage:
558 .vb
559      Mat A;
560      PetscInt alpha;
561      ...
562      PetscInfo(A,"Matrix uses parameter alpha=%" PetscInt_FMT "\n",alpha);
563 .ve
564 
565   Examples using Options:
566   Each call of the form
567 .vb
568      PetscInfo(obj, msg);
569      PetscInfo(obj, msg, arg1);
570      PetscInfo(obj, msg, arg1, arg2);
571 .ve
572   is evaluated as follows.
573 .vb
574     -info or -info :: prints `msg` to `PETSC_STDOUT`, for any PETSc `obj` regardless class or communicator
575     -info :mat:self prints `msg` to `PETSC_STDOUT` only if class of `obj` is `Mat`, and its communicator has size = 1
576     -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
577     -info :sys prints to `PETSC_STDOUT` only if `obj` is `NULL`
578     -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`.
579 .ve
580 
581   Fortran Notes:
582   This function does not take the `obj` argument, there is only the `PetscInfo()`
583   version, not `PetscInfo()` etc.
584 
585 .seealso: [](sec_PetscInfo), `PetscInfoAllow()`, `PetscInfoSetFromOptions()`, `PetscInfoEnabled()`, `PetscInfoSetFile()`, `PetscInfoGetFile()`, `PetscInfoSetClasses()`,
586           `PetscInfoGetClass()`, `PetscInfoGetInfo()`, `PetscInfoProcessClass()`, `PetscInfoSetFilterCommSelf()`, `PetscInfoDestroy()`, `PetscInfoDeactivateClass()`,
587           `PetscInfoActivateClass()`
588 M*/
589 PetscErrorCode PetscInfo_Private(const char func[], PetscObject obj, const char message[], ...)
590 {
591   PetscClassId classid = PETSC_SMALLEST_CLASSID;
592   PetscBool    enabled = PETSC_FALSE;
593   MPI_Comm     comm    = MPI_COMM_NULL;
594   PetscMPIInt  rank    = 0;
595   const char  *otype   = NULL;
596 
597   PetscFunctionBegin;
598   if (obj) {
599     PetscValidHeader(obj, 2);
600     classid = obj->classid;
601   }
602   PetscAssertPointer(message, 3);
603   PetscCall(PetscInfoEnabled(classid, &enabled));
604   if (!enabled) PetscFunctionReturn(PETSC_SUCCESS);
605   if (obj) {
606     PetscCall(PetscObjectGetComm(obj, &comm));
607     PetscCall(PetscObjectGetType(obj, &otype));
608     PetscCallMPI(MPI_Comm_rank(comm, &rank));
609   }
610   /* rank > 0 always jumps out */
611   if (rank) PetscFunctionReturn(PETSC_SUCCESS);
612   else {
613     PetscMPIInt size = 1;
614 
615     if (comm != MPI_COMM_NULL) PetscCallMPI(MPI_Comm_size(comm, &size));
616     /* If no self printing is allowed, and size too small, get out */
617     if ((PetscInfoCommFilter == PETSC_INFO_COMM_NO_SELF) && (size < 2)) PetscFunctionReturn(PETSC_SUCCESS);
618     /* If ONLY self printing, and size too big, get out */
619     if ((PetscInfoCommFilter == PETSC_INFO_COMM_ONLY_SELF) && (size > 1)) PetscFunctionReturn(PETSC_SUCCESS);
620   }
621   /* Mute info messages within this function */
622   {
623     const PetscBool oldflag = PetscLogPrintInfo;
624     va_list         Argp;
625     PetscMPIInt     urank;
626     char            string[8 * 1024];
627     size_t          fullLength, len;
628 
629     PetscLogPrintInfo = PETSC_FALSE;
630     PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &urank));
631     if (otype) {
632       PetscCall(PetscSNPrintf(string, PETSC_STATIC_ARRAY_LENGTH(string), "[%d] <%s:%s> %s(): ", urank, PetscInfoNames[classid - PETSC_SMALLEST_CLASSID], otype, func));
633     } else {
634       PetscCall(PetscSNPrintf(string, PETSC_STATIC_ARRAY_LENGTH(string), "[%d] <%s> %s(): ", urank, PetscInfoNames[classid - PETSC_SMALLEST_CLASSID], func));
635     }
636     PetscCall(PetscStrlen(string, &len));
637     va_start(Argp, message);
638     PetscCall(PetscVSNPrintf(string + len, 8 * 1024 - len, message, &fullLength, Argp));
639     va_end(Argp);
640     PetscCall(PetscVFPrintf_Internal(PetscInfoFile, "%s", string));
641     PetscCall(PetscFFlush(PetscInfoFile));
642     if (petsc_history) {
643       va_start(Argp, message);
644       PetscCall((*PetscVFPrintf)(petsc_history, message, Argp));
645       va_end(Argp);
646     }
647     PetscLogPrintInfo = oldflag;
648   }
649   PetscFunctionReturn(PETSC_SUCCESS);
650 }
651