xref: /petsc/src/sys/info/verboseinfo.c (revision bbfde98d24007149e2e73427fb24bfdd802107d3)
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 `filename` 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       Options Database Key:
274 .   -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, see `PetscInfo()`.
275 
276     Level: developer
277 
278 .seealso: `PetscInfo()`, `PetscInfoActivateClass()`, `PetscInfoDeactivateClass()`, `PetscInfoSetFromOptions()`
279 @*/
280 PetscErrorCode PetscInfoProcessClass(const char classname[], PetscInt numClassID, const PetscClassId classIDs[])
281 {
282   PetscBool enabled, exclude, found, opt;
283   char      logList[256];
284 
285   PetscFunctionBegin;
286   PetscValidCharPointer(classname, 1);
287   PetscAssert(numClassID > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of classids %" PetscInt_FMT " <= 0", numClassID);
288   if (numClassID) PetscValidPointer(classIDs, 3);
289   PetscCall(PetscInfoGetInfo(&enabled, NULL, &exclude, NULL, NULL));
290   PetscCall(PetscOptionsDeprecated_Private(NULL, "-info_exclude", NULL, "3.13", "Use ~ with -info to indicate classes to exclude"));
291   PetscCall(PetscOptionsGetString(NULL, NULL, "-info_exclude", logList, sizeof(logList), &opt));
292   if (opt) {
293     PetscBool pkg;
294 
295     PetscCall(PetscStrInList(classname, logList, ',', &pkg));
296     if (pkg) {
297       for (PetscInt i = 0; i < numClassID; ++i) PetscCall(PetscInfoDeactivateClass(classIDs[i]));
298     }
299   }
300   for (PetscInt i = 0; i < numClassID; ++i) {
301     const PetscClassId idx = classIDs[i] - PETSC_SMALLEST_CLASSID;
302 
303     PetscCall(PetscFree(PetscInfoNames[idx]));
304     PetscCall(PetscStrallocpy(classname, PetscInfoNames + idx));
305   }
306   PetscCall(PetscInfoGetClass(classname, &found));
307   if ((found && exclude) || (!found && !exclude)) {
308     if (PetscInfoNumClasses > 0) {
309       /* Check if -info was called empty */
310       for (PetscInt i = 0; i < numClassID; ++i) PetscCall(PetscInfoDeactivateClass(classIDs[i]));
311     }
312   } else {
313     for (PetscInt i = 0; i < numClassID; ++i) PetscCall(PetscInfoActivateClass(classIDs[i]));
314   }
315   PetscFunctionReturn(PETSC_SUCCESS);
316 }
317 
318 /*@
319     PetscInfoSetFilterCommSelf - Sets `PetscInfoCommFlag` enum to determine communicator filtering for `PetscInfo()`
320 
321     Not Collective
322 
323     Input Parameter:
324 .   commSelfFlag - Enum value indicating method with which to filter `PetscInfo()` based on the size of the communicator of the object calling `PetscInfo()`
325 
326     Options Database Key:
327 .   -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
328 
329     Level: advanced
330 
331 .seealso: `PetscInfo()`, `PetscInfoGetInfo()`
332 @*/
333 PetscErrorCode PetscInfoSetFilterCommSelf(PetscInfoCommFlag commSelfFlag)
334 {
335   PetscFunctionBegin;
336   PetscInfoCommFilter = commSelfFlag;
337   PetscFunctionReturn(PETSC_SUCCESS);
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 Key:
349 .   -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
350 
351     Level: advanced
352 
353     Note:
354     This function is called automatically during `PetscInitialize()` so users usually do not need to call it themselves.
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(PetscOptionsGetString(options, NULL, "-info", optstring, PETSC_STATIC_ARRAY_LENGTH(optstring), &set));
365   if (set) {
366     size_t            size_loc0_, size_loc1_, size_loc2_;
367     char             *loc0_ = NULL, *loc1_ = NULL, *loc2_ = NULL;
368     char            **loc1_array  = NULL;
369     PetscBool         loc1_invert = PETSC_FALSE, loc2_invert = PETSC_FALSE;
370     int               nLoc1_       = 0;
371     PetscInfoCommFlag commSelfFlag = PETSC_INFO_COMM_ALL;
372 
373     PetscInfoClassesSet = PETSC_TRUE;
374     PetscCall(PetscInfoAllow(PETSC_TRUE));
375     PetscCall(PetscStrallocpy(optstring, &loc0_));
376     PetscCall(PetscStrchr(loc0_, ':', &loc1_));
377     if (loc1_) {
378       *loc1_++ = 0;
379       if (*loc1_ == '~') {
380         loc1_invert = PETSC_TRUE;
381         ++loc1_;
382       }
383       PetscCall(PetscStrchr(loc1_, ':', &loc2_));
384     }
385     if (loc2_) {
386       *loc2_++ = 0;
387       if (*loc2_ == '~') {
388         loc2_invert = PETSC_TRUE;
389         ++loc2_;
390       }
391     }
392     PetscCall(PetscStrlen(loc0_, &size_loc0_));
393     PetscCall(PetscStrlen(loc1_, &size_loc1_));
394     PetscCall(PetscStrlen(loc2_, &size_loc2_));
395     if (size_loc1_) {
396       PetscCall(PetscStrtolower(loc1_));
397       PetscCall(PetscStrToArray(loc1_, ',', &nLoc1_, &loc1_array));
398     }
399     if (size_loc2_) {
400       PetscBool foundSelf;
401 
402       PetscCall(PetscStrtolower(loc2_));
403       PetscCall(PetscStrcmp("self", loc2_, &foundSelf));
404       if (foundSelf) commSelfFlag = loc2_invert ? PETSC_INFO_COMM_NO_SELF : PETSC_INFO_COMM_ONLY_SELF;
405     }
406     PetscCall(PetscInfoSetFile(size_loc0_ ? loc0_ : NULL, "w"));
407     PetscCall(PetscInfoSetClasses(loc1_invert, (PetscInt)nLoc1_, (const char *const *)loc1_array));
408     PetscCall(PetscInfoSetFilterCommSelf(commSelfFlag));
409     PetscCall(PetscStrToArrayDestroy(nLoc1_, loc1_array));
410     PetscCall(PetscFree(loc0_));
411   }
412   PetscFunctionReturn(PETSC_SUCCESS);
413 }
414 
415 /*@
416   PetscInfoDestroy - Destroys and resets internal `PetscInfo()` data structures.
417 
418   Not Collective
419 
420   Level: developer
421 
422   Note:
423   This is automatically called in `PetscFinalize()`. Useful for changing filters mid-program, or culling subsequent
424   `PetscInfo()` calls down the line.
425 
426 .seealso: `PetscInfo()`, `PetscInfoSetFromOptions()`
427 @*/
428 PetscErrorCode PetscInfoDestroy(void)
429 {
430   PetscFunctionBegin;
431   PetscCall(PetscInfoAllow(PETSC_FALSE));
432   PetscCall(PetscStrNArrayDestroy(PetscInfoNumClasses, &PetscInfoClassnames));
433   PetscCall(PetscFFlush(PetscInfoFile));
434   if (PetscInfoFilename) PetscCall(PetscFClose(PETSC_COMM_SELF, PetscInfoFile));
435   PetscCall(PetscFree(PetscInfoFilename));
436   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");
437   for (size_t i = 0; i < PETSC_STATIC_ARRAY_LENGTH(PetscInfoFlags); ++i) {
438     PetscInfoFlags[i] = 1;
439     PetscCall(PetscFree(PetscInfoNames[i]));
440   }
441 
442   PetscInfoClassesLocked = PETSC_FALSE;
443   PetscInfoInvertClasses = PETSC_FALSE;
444   PetscInfoClassesSet    = PETSC_FALSE;
445   PetscInfoNumClasses    = -1;
446   PetscInfoCommFilter    = PETSC_INFO_COMM_ALL;
447   PetscFunctionReturn(PETSC_SUCCESS);
448 }
449 
450 static PetscErrorCode PetscInfoSetClassActivation_Private(PetscClassId classid, int value)
451 {
452   PetscFunctionBegin;
453   if (!classid) classid = PETSC_SMALLEST_CLASSID;
454   PetscInfoFlags[classid - PETSC_SMALLEST_CLASSID] = value;
455   PetscFunctionReturn(PETSC_SUCCESS);
456 }
457 
458 /*@
459   PetscInfoDeactivateClass - Deactivates `PetscInfo()` messages for a PETSc object class.
460 
461   Not Collective
462 
463   Input Parameter:
464 . classid - The object class,  e.g., `MAT_CLASSID`, `SNES_CLASSID`, etc.
465 
466     Options Database Key:
467 .   -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
468 
469   Level: developer
470 
471   Note:
472   One can pass 0 to deactivate all messages that are not associated with an object.
473 
474 .seealso: `PetscInfoActivateClass()`, `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFromOptions()`
475 @*/
476 PetscErrorCode PetscInfoDeactivateClass(PetscClassId classid)
477 {
478   PetscFunctionBegin;
479   PetscCall(PetscInfoSetClassActivation_Private(classid, 0));
480   PetscFunctionReturn(PETSC_SUCCESS);
481 }
482 
483 /*@
484   PetscInfoActivateClass - Activates `PetscInfo()` messages for a PETSc object class.
485 
486   Not Collective
487 
488   Input Parameter:
489 . classid - The object class, e.g., `MAT_CLASSID`, `SNES_CLASSID`, etc.
490 
491     Options Database Key:
492 .   -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
493 
494   Level: developer
495 
496   Note:
497   One can pass 0 to activate all messages that are not associated with an object.
498 
499 .seealso: `PetscInfoDeactivateClass()`, `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFromOptions()`
500 @*/
501 PetscErrorCode PetscInfoActivateClass(PetscClassId classid)
502 {
503   PetscFunctionBegin;
504   PetscCall(PetscInfoSetClassActivation_Private(classid, 1));
505   PetscFunctionReturn(PETSC_SUCCESS);
506 }
507 
508 /*
509    If the option -history was used, then all printed PetscInfo()
510   messages are also printed to the history file, called by default
511   .petschistory in ones home directory.
512 */
513 PETSC_INTERN FILE *petsc_history;
514 
515 /*MC
516     PetscInfo - Logs informative data
517 
518    Synopsis:
519        #include <petscsys.h>
520        PetscErrorCode PetscInfo(PetscObject obj, const char message[])
521        PetscErrorCode PetscInfo(PetscObject obj, const char formatmessage[],arg1)
522        PetscErrorCode PetscInfo(PetscObject obj, const char formatmessage[],arg1,arg2)
523        ...
524 
525     Collective
526 
527     Input Parameters:
528 +   obj - object most closely associated with the logging statement or `NULL`
529 .   message - logging message
530 .   formatmessage - logging message using standard "printf" format
531 -   arg1, arg2, ... - arguments of the format
532 
533       Options Database Key:
534 .   -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
535 
536     Level: intermediate
537 
538     Notes:
539     `PetscInfo()` prints only from the first processor in the communicator of obj.
540     If obj is NULL, the `PETSC_COMM_SELF` communicator is used, i.e. every rank of `PETSC_COMM_WORLD` prints the message.
541 
542     The optional <list,of,classnames> is a comma separated list of enabled classes, e.g. vec,mat,ksp.
543     If this list is not specified, all classes are enabled.
544     Prepending the list with ~ means inverted selection, i.e. all classes except the listed are enabled.
545     A special classname `sys` relates to `PetscInfo()` with obj being `NULL`.
546 
547     The optional keyword `self` specifies that `PetscInfo()` is enabled only for a communicator size of 1 (e.g. `PETSC_COMM_SELF`).
548     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.
549 
550     All classname/self matching is case insensitive. Filename is case sensitive.
551 
552     Example of Usage:
553 .vb
554      Mat A;
555      PetscInt alpha;
556      ...
557      PetscInfo(A,"Matrix uses parameter alpha=%" PetscInt_FMT "\n",alpha);
558 .ve
559 
560     Options Examples:
561     Each call of the form
562 .vb
563      PetscInfo(obj, msg);
564      PetscInfo(obj, msg, arg1);
565      PetscInfo(obj, msg, arg1, arg2);
566 .ve
567     is evaluated as follows.
568 .vb
569     -info or -info :: prints msg to PETSC_STDOUT, for any obj regardless class or communicator
570     -info :mat:self prints msg to PETSC_STDOUT only if class of obj is Mat, and its communicator has size = 1
571     -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
572     -info :sys prints to PETSC_STDOUT only if obj is NULL
573     -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.
574 .ve
575     Fortran Note:
576     This function does not take the `obj` argument, there is only the `PetscInfo()`
577      version, not `PetscInfo()` etc.
578 
579 .seealso: `PetscInfoAllow()`, `PetscInfoSetFromOptions()`
580 M*/
581 PetscErrorCode PetscInfo_Private(const char func[], PetscObject obj, const char message[], ...)
582 {
583   PetscClassId classid = PETSC_SMALLEST_CLASSID;
584   PetscBool    enabled = PETSC_FALSE;
585   MPI_Comm     comm    = PETSC_COMM_SELF;
586   PetscMPIInt  rank;
587   const char  *otype = NULL;
588 
589   PetscFunctionBegin;
590   if (obj) {
591     PetscValidHeader(obj, 2);
592     classid = obj->classid;
593   }
594   PetscValidCharPointer(message, 3);
595   PetscCall(PetscInfoEnabled(classid, &enabled));
596   if (!enabled) PetscFunctionReturn(PETSC_SUCCESS);
597   if (obj) {
598     PetscCall(PetscObjectGetComm(obj, &comm));
599     PetscCall(PetscObjectGetType(obj, &otype));
600   }
601   PetscCallMPI(MPI_Comm_rank(comm, &rank));
602   /* rank > 0 always jumps out */
603   if (rank) PetscFunctionReturn(PETSC_SUCCESS);
604   else {
605     PetscMPIInt size;
606 
607     PetscCallMPI(MPI_Comm_size(comm, &size));
608     /* If no self printing is allowed, and size too small, get out */
609     if ((PetscInfoCommFilter == PETSC_INFO_COMM_NO_SELF) && (size < 2)) PetscFunctionReturn(PETSC_SUCCESS);
610     /* If ONLY self printing, and size too big, get out */
611     if ((PetscInfoCommFilter == PETSC_INFO_COMM_ONLY_SELF) && (size > 1)) PetscFunctionReturn(PETSC_SUCCESS);
612   }
613   /* Mute info messages within this function */
614   {
615     const PetscBool oldflag = PetscLogPrintInfo;
616     va_list         Argp;
617     PetscMPIInt     urank;
618     char            string[8 * 1024];
619     size_t          fullLength, len;
620 
621     PetscLogPrintInfo = PETSC_FALSE;
622     PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &urank));
623     if (otype) {
624       PetscCall(PetscSNPrintf(string, PETSC_STATIC_ARRAY_LENGTH(string), "[%d] <%s:%s> %s(): ", urank, PetscInfoNames[classid - PETSC_SMALLEST_CLASSID], otype, func));
625     } else {
626       PetscCall(PetscSNPrintf(string, PETSC_STATIC_ARRAY_LENGTH(string), "[%d] <%s> %s(): ", urank, PetscInfoNames[classid - PETSC_SMALLEST_CLASSID], func));
627     }
628     PetscCall(PetscStrlen(string, &len));
629     va_start(Argp, message);
630     PetscCall(PetscVSNPrintf(string + len, 8 * 1024 - len, message, &fullLength, Argp));
631     va_end(Argp);
632     PetscCall(PetscFPrintf(PETSC_COMM_SELF, PetscInfoFile, "%s", string));
633     PetscCall(PetscFFlush(PetscInfoFile));
634     if (petsc_history) {
635       va_start(Argp, message);
636       PetscCall((*PetscVFPrintf)(petsc_history, message, Argp));
637       va_end(Argp);
638     }
639     PetscLogPrintInfo = oldflag;
640   }
641   PetscFunctionReturn(PETSC_SUCCESS);
642 }
643