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, 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, 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, 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 `PetscClassid` 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: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoGetInfo()`, `PetscObjectGetClassid()`
50 @*/
PetscInfoEnabled(PetscClassId classid,PetscBool * enabled)51 PetscErrorCode PetscInfoEnabled(PetscClassId classid, PetscBool *enabled)
52 {
53 PetscFunctionBegin;
54 PetscAssertPointer(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: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoEnabled()`, `PetscInfoGetInfo()`, `PetscInfoSetFromOptions()`
71 @*/
PetscInfoAllow(PetscBool flag)72 PetscErrorCode PetscInfoAllow(PetscBool flag)
73 {
74 PetscFunctionBegin;
75 PetscLogPrintInfo = flag;
76 PetscFunctionReturn(PETSC_SUCCESS);
77 }
78
79 /*@
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, use `NULL` to write to `PETSC_STDOUT`.
86 - mode - Write mode passed to `PetscFOpen()`
87
88 Level: advanced
89
90 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoGetFile()`, `PetscInfoSetFromOptions()`, `PetscFOpen()`
91 @*/
PetscInfoSetFile(const char filename[],const char mode[])92 PetscErrorCode PetscInfoSetFile(const char filename[], const char mode[])
93 {
94 PetscFunctionBegin;
95 if (!PetscInfoFile) PetscInfoFile = PETSC_STDOUT;
96 PetscCall(PetscFree(PetscInfoFilename));
97 if (filename) {
98 PetscMPIInt rank;
99 char fname[PETSC_MAX_PATH_LEN], tname[11];
100
101 PetscAssertPointer(filename, 1);
102 PetscAssertPointer(mode, 2);
103 PetscCall(PetscFixFilename(filename, fname));
104 PetscCall(PetscStrallocpy(fname, &PetscInfoFilename));
105 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
106 PetscCall(PetscSNPrintf(tname, PETSC_STATIC_ARRAY_LENGTH(tname), ".%d", rank));
107 PetscCall(PetscStrlcat(fname, tname, PETSC_STATIC_ARRAY_LENGTH(fname)));
108 {
109 const PetscBool oldflag = PetscLogPrintInfo;
110
111 PetscLogPrintInfo = PETSC_FALSE;
112 PetscCall(PetscFOpen(PETSC_COMM_SELF, fname, mode, &PetscInfoFile));
113 PetscLogPrintInfo = oldflag;
114 /*
115 PetscFOpen will write to PETSC_STDOUT and not PetscInfoFile here, so we disable the
116 PetscInfo call inside it, and call it afterwards so that it actually writes to file
117 */
118 }
119 PetscCall(PetscInfo(NULL, "Opened PetscInfo file %s\n", fname));
120 }
121 PetscFunctionReturn(PETSC_SUCCESS);
122 }
123
124 /*@C
125 PetscInfoGetFile - Gets the `filename` and `FILE` pointer of the file where `PetscInfo()` prints to
126
127 Not Collective; No Fortran Support
128
129 Output Parameters:
130 + filename - The name of the output file
131 - InfoFile - The `FILE` pointer for the output file
132
133 Level: advanced
134
135 Note:
136 This routine allocates and copies the `filename` so that the `filename` survives `PetscInfoDestroy()`. The user is
137 therefore responsible for freeing the allocated `filename` pointer with `PetscFree()`
138
139 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoSetFile()`, `PetscInfoSetFromOptions()`, `PetscInfoDestroy()`
140 @*/
PetscInfoGetFile(char * filename[],FILE ** InfoFile)141 PetscErrorCode PetscInfoGetFile(char *filename[], FILE **InfoFile)
142 {
143 PetscFunctionBegin;
144 PetscAssertPointer(filename, 1);
145 PetscAssertPointer(InfoFile, 2);
146 PetscCall(PetscStrallocpy(PetscInfoFilename, filename));
147 *InfoFile = PetscInfoFile;
148 PetscFunctionReturn(PETSC_SUCCESS);
149 }
150
151 /*@C
152 PetscInfoSetClasses - Sets the classes which `PetscInfo()` is filtered for/against
153
154 Not Collective; No Fortran Support
155
156 Input Parameters:
157 + exclude - Whether or not to invert the filter, i.e. if exclude is true, `PetscInfo()` will print from every class that
158 is NOT one of the classes specified
159 . n - Number of classes to filter for (size of `classnames`)
160 - classnames - String array containing the names of classes to filter for, e.g. "vec"
161
162 Level: developer
163
164 Notes:
165 This function CANNOT be called after `PetscInfoGetClass()` or `PetscInfoProcessClass()` has been called, unless the user calls `PetscInfoDestroy()` first.
166
167 Names in the `classnames` list should correspond to the names returned by `PetscObjectGetClassName()`.
168
169 This function only sets the list of class names.
170 The actual filtering is deferred to `PetscInfoProcessClass()`, except of sys which is processed right away.
171 The reason for this is that we need to set the list of included/excluded classes before their classids are known.
172 Typically the classid is assigned and `PetscInfoProcessClass()` called in <Class>InitializePackage() (e.g. `VecInitializePackage()`).
173
174 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoGetClass()`, `PetscInfoProcessClass()`, `PetscInfoSetFromOptions()`, `PetscStrToArray()`, `PetscObjectGetName()`
175 @*/
PetscInfoSetClasses(PetscBool exclude,PetscInt n,const char * const * classnames)176 PetscErrorCode PetscInfoSetClasses(PetscBool exclude, PetscInt n, const char *const *classnames)
177 {
178 PetscFunctionBegin;
179 PetscCheck(!PetscInfoClassesLocked, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Trying to modify PetscInfo() configuration after it has been locked to a read-only state. Usually, this is an *error*! To re-enable modification, you must reset PetscInfo() by calling PetscInfoDestroy() first");
180 PetscCall(PetscStrNArrayDestroy(PetscInfoNumClasses, &PetscInfoClassnames));
181 PetscCall(PetscStrNArrayallocpy(n, classnames, &PetscInfoClassnames));
182 PetscInfoNumClasses = n;
183 PetscInfoInvertClasses = exclude;
184 /* Process sys class right away */
185 {
186 const PetscClassId id = PETSC_SMALLEST_CLASSID;
187
188 PetscCall(PetscInfoProcessClass("sys", 1, &id));
189 }
190 PetscInfoClassesSet = PETSC_TRUE;
191 PetscFunctionReturn(PETSC_SUCCESS);
192 }
193
194 /*@
195 PetscInfoGetClass - Indicates whether the provided `classname` is marked as a filter in `PetscInfo()` as set by `PetscInfoSetClasses()`
196
197 Not Collective
198
199 Input Parameter:
200 . classname - Name of the class to search for
201
202 Output Parameter:
203 . found - `PetscBool` indicating whether the classname was found
204
205 Level: developer
206
207 Note:
208 Use `PetscObjectGetName()` to retrieve an appropriate classname
209
210 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoSetClasses()`, `PetscInfoSetFromOptions()`, `PetscObjectGetName()`
211 @*/
PetscInfoGetClass(const char classname[],PetscBool * found)212 PetscErrorCode PetscInfoGetClass(const char classname[], PetscBool *found)
213 {
214 PetscInt unused;
215
216 PetscFunctionBegin;
217 PetscAssertPointer(classname, 1);
218 PetscAssertPointer(found, 2);
219 PetscCall(PetscEListFind(PetscInfoNumClasses, (const char *const *)PetscInfoClassnames, classname ? classname : "sys", &unused, found));
220 PetscInfoClassesLocked = PETSC_TRUE;
221 PetscFunctionReturn(PETSC_SUCCESS);
222 }
223
224 /*@
225 PetscInfoGetInfo - Returns the current state of several flags for `PetscInfo()`
226
227 Not Collective
228
229 Output Parameters:
230 + infoEnabled - `PETSC_TRUE` if `PetscInfoAllow`(`PETSC_TRUE`) has been called
231 . classesSet - `PETSC_TRUE` if the list of classes to filter for has been set
232 . exclude - `PETSC_TRUE` if the class filtering for `PetscInfo()` is inverted
233 . locked - `PETSC_TRUE` if the list of classes to filter for has been locked
234 - commSelfFlag - Enum indicating whether `PetscInfo()` will print for communicators of size 1, any size != 1, or all
235 communicators
236
237 Level: developer
238
239 Note:
240 Initially commSelfFlag = `PETSC_INFO_COMM_ALL`
241
242 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFilterCommSelf`, `PetscInfoSetFromOptions()`
243 @*/
PetscInfoGetInfo(PetscBool * infoEnabled,PetscBool * classesSet,PetscBool * exclude,PetscBool * locked,PetscInfoCommFlag * commSelfFlag)244 PetscErrorCode PetscInfoGetInfo(PetscBool *infoEnabled, PetscBool *classesSet, PetscBool *exclude, PetscBool *locked, PetscInfoCommFlag *commSelfFlag)
245 {
246 PetscFunctionBegin;
247 if (infoEnabled) PetscAssertPointer(infoEnabled, 1);
248 if (classesSet) PetscAssertPointer(classesSet, 2);
249 if (exclude) PetscAssertPointer(exclude, 3);
250 if (locked) PetscAssertPointer(locked, 4);
251 if (commSelfFlag) PetscAssertPointer(commSelfFlag, 5);
252 if (infoEnabled) *infoEnabled = PetscLogPrintInfo;
253 if (classesSet) *classesSet = PetscInfoClassesSet;
254 if (exclude) *exclude = PetscInfoInvertClasses;
255 if (locked) *locked = PetscInfoClassesLocked;
256 if (commSelfFlag) *commSelfFlag = PetscInfoCommFilter;
257 PetscFunctionReturn(PETSC_SUCCESS);
258 }
259
260 /*@
261 PetscInfoProcessClass - Activates or deactivates a class based on the filtering status of `PetscInfo()`
262
263 Not Collective
264
265 Input Parameters:
266 + classname - Name of the class to activate/deactivate `PetscInfo()` for
267 . numClassID - Number of entries in `classIDs`
268 - classIDs - Array containing all of the `PetscClassId`s associated with `classname`
269
270 Options Database Key:
271 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, see `PetscInfo()`.
272
273 Level: developer
274
275 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoActivateClass()`, `PetscInfoDeactivateClass()`, `PetscInfoSetFromOptions()`
276 @*/
PetscInfoProcessClass(const char classname[],PetscInt numClassID,const PetscClassId classIDs[])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 PetscAssertPointer(classname, 1);
284 PetscAssert(numClassID > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of classids %" PetscInt_FMT " <= 0", numClassID);
285 if (numClassID) PetscAssertPointer(classIDs, 3);
286 PetscCall(PetscInfoGetInfo(&enabled, NULL, &exclude, NULL, NULL));
287 PetscCall(PetscOptionsDeprecated_Private(NULL, "-info_exclude", NULL, "3.13", "Use ~ with -info to indicate classes to exclude"));
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 PetscCheck(PETSC_LARGEST_CLASSID - PETSC_SMALLEST_CLASSID < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(PetscInfoNames), PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscInfoNames array is too small for %s, need %d not %d", classname, PETSC_LARGEST_CLASSID - PETSC_SMALLEST_CLASSID + 1, (int)PETSC_STATIC_ARRAY_LENGTH(PetscInfoNames));
298 for (PetscInt i = 0; i < numClassID; ++i) {
299 const PetscClassId idx = classIDs[i] - PETSC_SMALLEST_CLASSID;
300
301 PetscCall(PetscFree(PetscInfoNames[idx]));
302 PetscCall(PetscStrallocpy(classname, PetscInfoNames + idx));
303 }
304 PetscCall(PetscInfoGetClass(classname, &found));
305 if ((found && exclude) || (!found && !exclude)) {
306 if (PetscInfoNumClasses > 0) {
307 /* Check if -info was called empty */
308 for (PetscInt i = 0; i < numClassID; ++i) PetscCall(PetscInfoDeactivateClass(classIDs[i]));
309 }
310 } else {
311 for (PetscInt i = 0; i < numClassID; ++i) PetscCall(PetscInfoActivateClass(classIDs[i]));
312 }
313 PetscFunctionReturn(PETSC_SUCCESS);
314 }
315
316 /*@
317 PetscInfoSetFilterCommSelf - Sets `PetscInfoCommFlag` enum to determine communicator filtering for `PetscInfo()`
318
319 Not Collective
320
321 Input Parameter:
322 . commSelfFlag - Enum value indicating method with which to filter `PetscInfo()` based on the size of the communicator of the object calling `PetscInfo()`
323
324 Options Database Key:
325 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
326
327 Level: advanced
328
329 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoGetInfo()`
330 @*/
PetscInfoSetFilterCommSelf(PetscInfoCommFlag commSelfFlag)331 PetscErrorCode PetscInfoSetFilterCommSelf(PetscInfoCommFlag commSelfFlag)
332 {
333 PetscFunctionBegin;
334 PetscInfoCommFilter = commSelfFlag;
335 PetscFunctionReturn(PETSC_SUCCESS);
336 }
337
338 /*@
339 PetscInfoSetFromOptions - Configure `PetscInfo()` using command line options, enabling or disabling various calls to `PetscInfo()`
340
341 Not Collective
342
343 Input Parameter:
344 . options - Options database, use `NULL` for default global database
345
346 Options Database Key:
347 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
348
349 Level: advanced
350
351 Note:
352 This function is called automatically during `PetscInitialize()` so users usually do not need to call it themselves.
353
354 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFile()`, `PetscInfoSetClasses()`, `PetscInfoSetFilterCommSelf()`, `PetscInfoDestroy()`
355 @*/
PetscInfoSetFromOptions(PetscOptions options)356 PetscErrorCode PetscInfoSetFromOptions(PetscOptions options)
357 {
358 char optstring[PETSC_MAX_PATH_LEN];
359 PetscBool set;
360
361 PetscFunctionBegin;
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, 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 Level: developer
419
420 Notes:
421 This is automatically called in `PetscFinalize()`. Useful for changing filters mid-program, or culling subsequent
422 `PetscInfo()` calls down the line.
423
424 Users calling this routine midway through a program should note that `PetscInfoDestroy()`
425 constitutes a full reset of `PetscInfo()`. It flushes, then closes, the current info file,
426 re-enables all classes, and resets all internal state. Finally -- and perhaps crucially -- it
427 disables `PetscInfo()` as-if-by `PetscInfoAllow(PETSC_FALSE)`.
428
429 .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoSetFromOptions()`
430 @*/
PetscInfoDestroy(void)431 PetscErrorCode PetscInfoDestroy(void)
432 {
433 PetscFunctionBegin;
434 PetscCall(PetscInfoAllow(PETSC_FALSE));
435 PetscCall(PetscStrNArrayDestroy(PetscInfoNumClasses, &PetscInfoClassnames));
436 if (PetscInfoFile) PetscCall(PetscFFlush(PetscInfoFile));
437 if (PetscInfoFilename) {
438 PetscAssert(PetscInfoFile, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Have non-null PetscInfo file '%s', but corresponding FILE handle is null!", PetscInfoFilename);
439 PetscCall(PetscFree(PetscInfoFilename));
440 PetscCall(PetscFClose(PETSC_COMM_SELF, PetscInfoFile));
441 }
442 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");
443 for (size_t i = 0; i < PETSC_STATIC_ARRAY_LENGTH(PetscInfoFlags); ++i) {
444 PetscInfoFlags[i] = 1;
445 PetscCall(PetscFree(PetscInfoNames[i]));
446 }
447
448 PetscInfoFile = NULL;
449 PetscInfoClassesLocked = PETSC_FALSE;
450 PetscInfoInvertClasses = PETSC_FALSE;
451 PetscInfoClassesSet = PETSC_FALSE;
452 PetscInfoNumClasses = -1;
453 PetscInfoCommFilter = PETSC_INFO_COMM_ALL;
454 PetscFunctionReturn(PETSC_SUCCESS);
455 }
456
PetscInfoSetClassActivation_Private(PetscClassId classid,int value)457 static PetscErrorCode PetscInfoSetClassActivation_Private(PetscClassId classid, int value)
458 {
459 PetscFunctionBegin;
460 if (!classid) classid = PETSC_SMALLEST_CLASSID;
461 PetscInfoFlags[classid - PETSC_SMALLEST_CLASSID] = value;
462 PetscFunctionReturn(PETSC_SUCCESS);
463 }
464
465 /*@
466 PetscInfoDeactivateClass - Deactivates `PetscInfo()` messages for a PETSc object class.
467
468 Not Collective
469
470 Input Parameter:
471 . classid - The object class, e.g., `MAT_CLASSID`, `SNES_CLASSID`, etc.
472
473 Options Database Key:
474 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
475
476 Level: developer
477
478 Note:
479 One can pass 0 to deactivate all messages that are not associated with an object.
480
481 .seealso: [](sec_PetscInfo), `PetscInfoActivateClass()`, `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFromOptions()`
482 @*/
PetscInfoDeactivateClass(PetscClassId classid)483 PetscErrorCode PetscInfoDeactivateClass(PetscClassId classid)
484 {
485 PetscFunctionBegin;
486 PetscCall(PetscInfoSetClassActivation_Private(classid, 0));
487 PetscFunctionReturn(PETSC_SUCCESS);
488 }
489
490 /*@
491 PetscInfoActivateClass - Activates `PetscInfo()` messages for a PETSc object class.
492
493 Not Collective
494
495 Input Parameter:
496 . classid - The object class, e.g., `MAT_CLASSID`, `SNES_CLASSID`, etc.
497
498 Options Database Key:
499 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.
500
501 Level: developer
502
503 Note:
504 One can pass 0 to activate all messages that are not associated with an object.
505
506 .seealso: [](sec_PetscInfo), `PetscInfoDeactivateClass()`, `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFromOptions()`
507 @*/
PetscInfoActivateClass(PetscClassId classid)508 PetscErrorCode PetscInfoActivateClass(PetscClassId classid)
509 {
510 PetscFunctionBegin;
511 PetscCall(PetscInfoSetClassActivation_Private(classid, 1));
512 PetscFunctionReturn(PETSC_SUCCESS);
513 }
514
515 /*
516 If the option -history was used, then all printed PetscInfo()
517 messages are also printed to the history file, called by default
518 .petschistory in ones home directory.
519 */
520 PETSC_INTERN FILE *petsc_history;
521 PETSC_INTERN PetscErrorCode PetscVFPrintf_Internal(FILE *, const char[], ...);
522
523 /*MC
524 PetscInfo - Logs informative data
525
526 Synopsis:
527 #include <petsclog.h>
528 PetscErrorCode PetscInfo(PetscObject obj, const char message[], ...)
529
530 Collective
531
532 Input Parameters:
533 + obj - object most closely associated with the logging statement or `NULL`
534 - message - logging message using standard "printf" format
535
536 Options Database Key:
537 . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed
538
539 Level: intermediate
540
541 Notes:
542 `PetscInfo()` prints only from the first processor in the communicator of `obj`.
543 If `obj` is `NULL`, the `PETSC_COMM_SELF` communicator is used, i.e. every rank of `PETSC_COMM_WORLD` prints the message.
544
545 The optional <list,of,classnames> is a comma separated list of enabled classes, e.g. `vec,mat,ksp`.
546 If this list is not specified, all classes are enabled.
547 Prepending the list with ~ means inverted selection, i.e. all classes except the listed are enabled.
548 A special classname `sys` relates to `PetscInfo()` with `obj` being `NULL`.
549
550 The optional keyword `self` specifies that `PetscInfo()` is enabled only for a communicator size of 1 (e.g. `PETSC_COMM_SELF`).
551 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.
552
553 All classname/self matching is case insensitive. Filename is case sensitive.
554
555 Example of Usage:
556 .vb
557 Mat A;
558 PetscInt alpha;
559 ...
560 PetscInfo(A,"Matrix uses parameter alpha=%" PetscInt_FMT "\n",alpha);
561 .ve
562
563 Examples using Options:
564 Each call of the form
565 .vb
566 PetscInfo(obj, msg);
567 PetscInfo(obj, msg, arg1);
568 PetscInfo(obj, msg, arg1, arg2);
569 .ve
570 is evaluated as follows.
571 .vb
572 -info or -info :: prints `msg` to `PETSC_STDOUT`, for any PETSc `obj` regardless class or communicator
573 -info :mat:self prints `msg` to `PETSC_STDOUT` only if class of `obj` is `Mat`, and its communicator has size = 1
574 -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
575 -info :sys prints to `PETSC_STDOUT` only if `obj` is `NULL`
576 -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`.
577 .ve
578
579 Fortran Notes:
580 This function does not take the `obj` argument, there is only the `PetscInfo()`
581 version, not `PetscInfo()` etc.
582
583 .seealso: [](sec_PetscInfo), `PetscInfoAllow()`, `PetscInfoSetFromOptions()`, `PetscInfoEnabled()`, `PetscInfoSetFile()`, `PetscInfoGetFile()`, `PetscInfoSetClasses()`,
584 `PetscInfoGetClass()`, `PetscInfoGetInfo()`, `PetscInfoProcessClass()`, `PetscInfoSetFilterCommSelf()`, `PetscInfoDestroy()`, `PetscInfoDeactivateClass()`,
585 `PetscInfoActivateClass()`
586 M*/
PetscInfo_Private(const char func[],PetscObject obj,const char message[],...)587 PetscErrorCode PetscInfo_Private(const char func[], PetscObject obj, const char message[], ...)
588 {
589 PetscClassId classid = PETSC_SMALLEST_CLASSID;
590 PetscBool enabled = PETSC_FALSE;
591 MPI_Comm comm = MPI_COMM_NULL;
592 PetscMPIInt rank = 0;
593 const char *otype = NULL;
594
595 PetscFunctionBegin;
596 if (obj) {
597 PetscValidHeader(obj, 2);
598 classid = obj->classid;
599 }
600 PetscAssertPointer(message, 3);
601 PetscCall(PetscInfoEnabled(classid, &enabled));
602 if (!enabled) PetscFunctionReturn(PETSC_SUCCESS);
603 if (obj) {
604 PetscCall(PetscObjectGetComm(obj, &comm));
605 PetscCall(PetscObjectGetType(obj, &otype));
606 PetscCallMPI(MPI_Comm_rank(comm, &rank));
607 }
608 /* rank > 0 always jumps out */
609 if (rank) PetscFunctionReturn(PETSC_SUCCESS);
610 else {
611 PetscMPIInt size = 1;
612
613 if (comm != MPI_COMM_NULL) PetscCallMPI(MPI_Comm_size(comm, &size));
614 /* If no self printing is allowed, and size too small, get out */
615 if ((PetscInfoCommFilter == PETSC_INFO_COMM_NO_SELF) && (size < 2)) PetscFunctionReturn(PETSC_SUCCESS);
616 /* If ONLY self printing, and size too big, get out */
617 if ((PetscInfoCommFilter == PETSC_INFO_COMM_ONLY_SELF) && (size > 1)) PetscFunctionReturn(PETSC_SUCCESS);
618 }
619 /* Mute info messages within this function */
620 {
621 const PetscBool oldflag = PetscLogPrintInfo;
622 va_list Argp;
623 PetscMPIInt urank;
624 char string[8 * 1024];
625 size_t fullLength, len;
626
627 PetscLogPrintInfo = PETSC_FALSE;
628 PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &urank));
629 if (otype) {
630 PetscCall(PetscSNPrintf(string, PETSC_STATIC_ARRAY_LENGTH(string), "[%d] <%s:%s> %s(): ", urank, PetscInfoNames[classid - PETSC_SMALLEST_CLASSID], otype, func));
631 } else {
632 PetscCall(PetscSNPrintf(string, PETSC_STATIC_ARRAY_LENGTH(string), "[%d] <%s> %s(): ", urank, PetscInfoNames[classid - PETSC_SMALLEST_CLASSID], func));
633 }
634 PetscCall(PetscStrlen(string, &len));
635 va_start(Argp, message);
636 PetscCall(PetscVSNPrintf(string + len, 8 * 1024 - len, message, &fullLength, Argp));
637 va_end(Argp);
638 PetscCall(PetscVFPrintf_Internal(PetscInfoFile, "%s", string));
639 PetscCall(PetscFFlush(PetscInfoFile));
640 if (petsc_history) {
641 va_start(Argp, message);
642 PetscCall((*PetscVFPrintf)(petsc_history, message, Argp));
643 va_end(Argp);
644 }
645 PetscLogPrintInfo = oldflag;
646 }
647 PetscFunctionReturn(PETSC_SUCCESS);
648 }
649