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