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