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