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