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