Actual source code: verboseinfo.c

  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>

  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.

 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.

 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;

 32: /*@
 33:   PetscInfoEnabled - Checks whether a given `PetscClassid` is allowed to print using `PetscInfo()`

 35:   Not Collective

 37:   Input Parameter:
 38: . classid - `PetscClassid` retrieved from a `PetscObject` e.g. `VEC_CLASSID`

 40:   Output Parameter:
 41: . enabled - `PetscBool` indicating whether this classid is allowed to print

 43:   Level: advanced

 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.

 49: .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoGetInfo()`, `PetscObjectGetClassid()`
 50: @*/
 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: }

 60: /*@
 61:   PetscInfoAllow - Enables/disables `PetscInfo()` messages

 63:   Not Collective

 65:   Input Parameter:
 66: . flag - `PETSC_TRUE` or `PETSC_FALSE`

 68:   Level: advanced

 70: .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoEnabled()`, `PetscInfoGetInfo()`, `PetscInfoSetFromOptions()`
 71: @*/
 72: PetscErrorCode PetscInfoAllow(PetscBool flag)
 73: {
 74:   PetscFunctionBegin;
 75:   PetscLogPrintInfo = flag;
 76:   PetscFunctionReturn(PETSC_SUCCESS);
 77: }

 79: /*@
 80:   PetscInfoSetFile - Sets the printing destination for all `PetscInfo()` calls

 82:   Not Collective

 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()`

 88:   Level: advanced

 90: .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoGetFile()`, `PetscInfoSetFromOptions()`, `PetscFOpen()`
 91: @*/
 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];

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;

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: }

124: /*@C
125:   PetscInfoGetFile - Gets the `filename` and `FILE` pointer of the file where `PetscInfo()` prints to

127:   Not Collective; No Fortran Support

129:   Output Parameters:
130: + filename - The name of the output file
131: - InfoFile - The `FILE` pointer for the output file

133:   Level: advanced

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()`

139: .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoSetFile()`, `PetscInfoSetFromOptions()`, `PetscInfoDestroy()`
140: @*/
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: }

151: /*@C
152:   PetscInfoSetClasses - Sets the classes which `PetscInfo()` is filtered for/against

154:   Not Collective; No Fortran Support

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"

162:   Level: developer

164:   Notes:
165:   This function CANNOT be called after `PetscInfoGetClass()` or `PetscInfoProcessClass()` has been called, unless the user calls `PetscInfoDestroy()` first.

167:   Names in the `classnames` list should correspond to the names returned by `PetscObjectGetClassName()`.

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()`).

174: .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoGetClass()`, `PetscInfoProcessClass()`, `PetscInfoSetFromOptions()`, `PetscStrToArray()`, `PetscObjectGetName()`
175: @*/
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;

188:     PetscCall(PetscInfoProcessClass("sys", 1, &id));
189:   }
190:   PetscInfoClassesSet = PETSC_TRUE;
191:   PetscFunctionReturn(PETSC_SUCCESS);
192: }

194: /*@
195:   PetscInfoGetClass - Indicates whether the provided `classname` is marked as a filter in `PetscInfo()` as set by `PetscInfoSetClasses()`

197:   Not Collective

199:   Input Parameter:
200: . classname - Name of the class to search for

202:   Output Parameter:
203: . found - `PetscBool` indicating whether the classname was found

205:   Level: developer

207:   Note:
208:   Use `PetscObjectGetName()` to retrieve an appropriate classname

210: .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoSetClasses()`, `PetscInfoSetFromOptions()`, `PetscObjectGetName()`
211: @*/
212: PetscErrorCode PetscInfoGetClass(const char classname[], PetscBool *found)
213: {
214:   PetscInt unused;

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: }

224: /*@
225:   PetscInfoGetInfo - Returns the current state of several flags for `PetscInfo()`

227:   Not Collective

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

237:   Level: developer

239:   Note:
240:   Initially commSelfFlag = `PETSC_INFO_COMM_ALL`

242: .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFilterCommSelf`, `PetscInfoSetFromOptions()`
243: @*/
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: }

260: /*@
261:   PetscInfoProcessClass - Activates or deactivates a class based on the filtering status of `PetscInfo()`

263:   Not Collective

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`

270:   Options Database Key:
271: . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, see `PetscInfo()`.

273:   Level: developer

275: .seealso: [](sec_PetscInfo), `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];

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;

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 %" PetscInt_FMT " not %" PetscInt_FMT, classname, (PetscInt)(PETSC_LARGEST_CLASSID - PETSC_SMALLEST_CLASSID + 1), (PetscInt)PETSC_STATIC_ARRAY_LENGTH(PetscInfoNames));
298:   for (PetscInt i = 0; i < numClassID; ++i) {
299:     const PetscClassId idx = classIDs[i] - PETSC_SMALLEST_CLASSID;

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: }

316: /*@
317:   PetscInfoSetFilterCommSelf - Sets `PetscInfoCommFlag` enum to determine communicator filtering for `PetscInfo()`

319:   Not Collective

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()`

324:   Options Database Key:
325: . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.

327:   Level: advanced

329: .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoGetInfo()`
330: @*/
331: PetscErrorCode PetscInfoSetFilterCommSelf(PetscInfoCommFlag commSelfFlag)
332: {
333:   PetscFunctionBegin;
334:   PetscInfoCommFilter = commSelfFlag;
335:   PetscFunctionReturn(PETSC_SUCCESS);
336: }

338: /*@
339:   PetscInfoSetFromOptions - Configure `PetscInfo()` using command line options, enabling or disabling various calls to `PetscInfo()`

341:   Not Collective

343:   Input Parameter:
344: . options - Options database, use `NULL` for default global database

346:   Options Database Key:
347: . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.

349:   Level: advanced

351:   Note:
352:   This function is called automatically during `PetscInitialize()` so users usually do not need to call it themselves.

354: .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFile()`, `PetscInfoSetClasses()`, `PetscInfoSetFilterCommSelf()`, `PetscInfoDestroy()`
355: @*/
356: PetscErrorCode PetscInfoSetFromOptions(PetscOptions options)
357: {
358:   char      optstring[PETSC_MAX_PATH_LEN];
359:   PetscBool set;

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;

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;

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: }

413: /*@
414:   PetscInfoDestroy - Destroys and resets internal `PetscInfo()` data structures.

416:   Not Collective

418:   Level: developer

420:   Notes:
421:   This is automatically called in `PetscFinalize()`. Useful for changing filters mid-program, or culling subsequent
422:   `PetscInfo()` calls down the line.

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)`.

429: .seealso: [](sec_PetscInfo), `PetscInfo()`, `PetscInfoSetFromOptions()`
430: @*/
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:   }

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: }

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: }

465: /*@
466:   PetscInfoDeactivateClass - Deactivates `PetscInfo()` messages for a PETSc object class.

468:   Not Collective

470:   Input Parameter:
471: . classid - The object class,  e.g., `MAT_CLASSID`, `SNES_CLASSID`, etc.

473:   Options Database Key:
474: . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.

476:   Level: developer

478:   Note:
479:   One can pass 0 to deactivate all messages that are not associated with an object.

481: .seealso: [](sec_PetscInfo), `PetscInfoActivateClass()`, `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFromOptions()`
482: @*/
483: PetscErrorCode PetscInfoDeactivateClass(PetscClassId classid)
484: {
485:   PetscFunctionBegin;
486:   PetscCall(PetscInfoSetClassActivation_Private(classid, 0));
487:   PetscFunctionReturn(PETSC_SUCCESS);
488: }

490: /*@
491:   PetscInfoActivateClass - Activates `PetscInfo()` messages for a PETSc object class.

493:   Not Collective

495:   Input Parameter:
496: . classid - The object class, e.g., `MAT_CLASSID`, `SNES_CLASSID`, etc.

498:   Options Database Key:
499: . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See `PetscInfo()`.

501:   Level: developer

503:   Note:
504:   One can pass 0 to activate all messages that are not associated with an object.

506: .seealso: [](sec_PetscInfo), `PetscInfoDeactivateClass()`, `PetscInfo()`, `PetscInfoAllow()`, `PetscInfoSetFromOptions()`
507: @*/
508: PetscErrorCode PetscInfoActivateClass(PetscClassId classid)
509: {
510:   PetscFunctionBegin;
511:   PetscCall(PetscInfoSetClassActivation_Private(classid, 1));
512:   PetscFunctionReturn(PETSC_SUCCESS);
513: }

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[], ...);

523: /*MC
524:   PetscInfo - Logs informative data

526:   Synopsis:
527: #include <petsclog.h>
528:   PetscErrorCode PetscInfo(PetscObject obj, const char message[], ...)

530:   Collective

532:   Input Parameters:
533: + obj     - object most closely associated with the logging statement or `NULL`
534: - message - logging message using standard "printf" format

536:   Options Database Key:
537: . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed

539:   Level: intermediate

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.

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`.

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.

553:   All classname/self matching is case insensitive. Filename is case sensitive.

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

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

579:   Fortran Notes:
580:   This function does not take the `obj` argument, there is only the `PetscInfo()`
581:   version, not `PetscInfo()` etc.

583: .seealso: [](sec_PetscInfo), `PetscInfoAllow()`, `PetscInfoSetFromOptions()`, `PetscInfoEnabled()`, `PetscInfoSetFile()`, `PetscInfoGetFile()`, `PetscInfoSetClasses()`,
584:           `PetscInfoGetClass()`, `PetscInfoGetInfo()`, `PetscInfoProcessClass()`, `PetscInfoSetFilterCommSelf()`, `PetscInfoDestroy()`, `PetscInfoDeactivateClass()`,
585:           `PetscInfoActivateClass()`
586: M*/
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;

595:   PetscFunctionBegin;
596:   if (obj) {
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;

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;

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: }