xref: /petsc/src/sys/info/verboseinfo.c (revision a68bbae58a07f2fb515cab24a67de1159d72e8a2)
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 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: `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   PetscFunctionBegin;
426   PetscCall(PetscInfoAllow(PETSC_FALSE));
427   PetscCall(PetscStrNArrayDestroy(PetscInfoNumClasses, &PetscInfoClassnames));
428   PetscCall(PetscFFlush(PetscInfoFile));
429   if (PetscInfoFilename) PetscCall(PetscFClose(PETSC_COMM_SELF, PetscInfoFile));
430   PetscCall(PetscFree(PetscInfoFilename));
431   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");
432   for (size_t i = 0; i < PETSC_STATIC_ARRAY_LENGTH(PetscInfoFlags); ++i) {
433     PetscInfoFlags[i] = 1;
434     PetscCall(PetscFree(PetscInfoNames[i]));
435   }
436 
437   PetscInfoClassesLocked = PETSC_FALSE;
438   PetscInfoInvertClasses = PETSC_FALSE;
439   PetscInfoClassesSet    = PETSC_FALSE;
440   PetscInfoNumClasses    = -1;
441   PetscInfoCommFilter    = PETSC_INFO_COMM_ALL;
442   PetscFunctionReturn(PETSC_SUCCESS);
443 }
444 
445 static PetscErrorCode PetscInfoSetClassActivation_Private(PetscClassId classid, int value)
446 {
447   PetscFunctionBegin;
448   if (!classid) classid = PETSC_SMALLEST_CLASSID;
449   PetscInfoFlags[classid - PETSC_SMALLEST_CLASSID] = value;
450   PetscFunctionReturn(PETSC_SUCCESS);
451 }
452 
453 /*@
454   PetscInfoDeactivateClass - Deactivates `PetscInfo()` messages for a PETSc object class.
455 
456   Not Collective
457 
458   Input Parameter:
459 . classid - The object class,  e.g., `MAT_CLASSID`, `SNES_CLASSID`, etc.
460 
461   Level: developer
462 
463   Note:
464   One can pass 0 to deactivate all messages that are not associated with an object.
465 
466 .seealso: `PetscInfoActivateClass()`, `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFromOptions()`
467 @*/
468 PetscErrorCode PetscInfoDeactivateClass(PetscClassId classid)
469 {
470   PetscFunctionBegin;
471   PetscCall(PetscInfoSetClassActivation_Private(classid, 0));
472   PetscFunctionReturn(PETSC_SUCCESS);
473 }
474 
475 /*@
476   PetscInfoActivateClass - Activates `PetscInfo()` messages for a PETSc object class.
477 
478   Not Collective
479 
480   Input Parameter:
481 . classid - The object class, e.g., `MAT_CLASSID`, `SNES_CLASSID`, etc.
482 
483   Level: developer
484 
485   Note:
486   One can pass 0 to activate all messages that are not associated with an object.
487 
488 .seealso: `PetscInfoDeactivateClass()`, `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFromOptions()`
489 @*/
490 PetscErrorCode PetscInfoActivateClass(PetscClassId classid)
491 {
492   PetscFunctionBegin;
493   PetscCall(PetscInfoSetClassActivation_Private(classid, 1));
494   PetscFunctionReturn(PETSC_SUCCESS);
495 }
496 
497 /*
498    If the option -history was used, then all printed PetscInfo()
499   messages are also printed to the history file, called by default
500   .petschistory in ones home directory.
501 */
502 PETSC_INTERN FILE *petsc_history;
503 
504 /*MC
505     PetscInfo - Logs informative data
506 
507    Synopsis:
508        #include <petscsys.h>
509        PetscErrorCode PetscInfo(PetscObject obj, const char message[])
510        PetscErrorCode PetscInfo(PetscObject obj, const char formatmessage[],arg1)
511        PetscErrorCode PetscInfo(PetscObject obj, const char formatmessage[],arg1,arg2)
512        ...
513 
514     Collective
515 
516     Input Parameters:
517 +   obj - object most closely associated with the logging statement or `NULL`
518 .   message - logging message
519 .   formatmessage - logging message using standard "printf" format
520 -   arg1, arg2, ... - arguments of the format
521 
522     Level: intermediate
523 
524     Notes:
525     `PetscInfo()` prints only from the first processor in the communicator of obj.
526     If obj is NULL, the `PETSC_COMM_SELF` communicator is used, i.e. every rank of `PETSC_COMM_WORLD` prints the message.
527 
528     Extent of the printed messages can be controlled using the option database key -info as follows.
529 
530 $   -info [filename][:[~]<list,of,classnames>[:[~]self]]
531 
532     No filename means standard output `PETSC_STDOUT` is used.
533 
534     The optional <list,of,classnames> is a comma separated list of enabled classes, e.g. vec,mat,ksp.
535     If this list is not specified, all classes are enabled.
536     Prepending the list with ~ means inverted selection, i.e. all classes except the listed are enabled.
537     A special classname sys relates to PetscInfo() with obj being NULL.
538 
539     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.
540     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.
541 
542     All classname/self matching is case insensitive. Filename is case sensitive.
543 
544     Example of Usage:
545 .vb
546      Mat A;
547      PetscInt alpha;
548      ...
549      PetscInfo(A,"Matrix uses parameter alpha=%" PetscInt_FMT "\n",alpha);
550 .ve
551 
552     Options Examples:
553     Each call of the form
554 .vb
555      PetscInfo(obj, msg);
556      PetscInfo(obj, msg, arg1);
557      PetscInfo(obj, msg, arg1, arg2);
558 .ve
559     is evaluated as follows.
560 .vb
561     -info or -info :: prints msg to PETSC_STDOUT, for any obj regardless class or communicator
562     -info :mat:self prints msg to PETSC_STDOUT only if class of obj is Mat, and its communicator has size = 1
563     -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
564     -info :sys prints to PETSC_STDOUT only if obj is NULL
565     -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.
566 .ve
567     Fortran Note:
568     This function does not take the obj argument, there is only the `PetscInfo()`
569      version, not `PetscInfo()` etc.
570 
571 .seealso: `PetscInfoAllow()`, `PetscInfoSetFromOptions()`
572 M*/
573 PetscErrorCode PetscInfo_Private(const char func[], PetscObject obj, const char message[], ...)
574 {
575   PetscClassId classid = PETSC_SMALLEST_CLASSID;
576   PetscBool    enabled = PETSC_FALSE;
577   MPI_Comm     comm    = PETSC_COMM_SELF;
578   PetscMPIInt  rank;
579 
580   PetscFunctionBegin;
581   if (obj) {
582     PetscValidHeader(obj, 2);
583     classid = obj->classid;
584   }
585   PetscValidCharPointer(message, 3);
586   PetscCall(PetscInfoEnabled(classid, &enabled));
587   if (!enabled) PetscFunctionReturn(PETSC_SUCCESS);
588   if (obj) PetscCall(PetscObjectGetComm(obj, &comm));
589   PetscCallMPI(MPI_Comm_rank(comm, &rank));
590   /* rank > 0 always jumps out */
591   if (rank) PetscFunctionReturn(PETSC_SUCCESS);
592   else {
593     PetscMPIInt size;
594 
595     PetscCallMPI(MPI_Comm_size(comm, &size));
596     /* If no self printing is allowed, and size too small, get out */
597     if ((PetscInfoCommFilter == PETSC_INFO_COMM_NO_SELF) && (size < 2)) PetscFunctionReturn(PETSC_SUCCESS);
598     /* If ONLY self printing, and size too big, get out */
599     if ((PetscInfoCommFilter == PETSC_INFO_COMM_ONLY_SELF) && (size > 1)) PetscFunctionReturn(PETSC_SUCCESS);
600   }
601   /* Mute info messages within this function */
602   {
603     const PetscBool oldflag = PetscLogPrintInfo;
604     va_list         Argp;
605     PetscMPIInt     urank;
606     char            string[8 * 1024];
607     size_t          fullLength, len;
608 
609     PetscLogPrintInfo = PETSC_FALSE;
610     PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &urank));
611     PetscCall(PetscSNPrintf(string, PETSC_STATIC_ARRAY_LENGTH(string), "[%d] <%s> %s(): ", urank, PetscInfoNames[classid - PETSC_SMALLEST_CLASSID], func));
612     PetscCall(PetscStrlen(string, &len));
613     va_start(Argp, message);
614     PetscCall(PetscVSNPrintf(string + len, 8 * 1024 - len, message, &fullLength, Argp));
615     va_end(Argp);
616     PetscCall(PetscFPrintf(PETSC_COMM_SELF, PetscInfoFile, "%s", string));
617     PetscCall(PetscFFlush(PetscInfoFile));
618     if (petsc_history) {
619       va_start(Argp, message);
620       PetscCall((*PetscVFPrintf)(petsc_history, message, Argp));
621       va_end(Argp);
622     }
623     PetscLogPrintInfo = oldflag;
624   }
625   PetscFunctionReturn(PETSC_SUCCESS);
626 }
627