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