Actual source code: plog.c

      1: /*
      2:       PETSc code to log object creation and destruction and PETSc events.

      4:       This provides the public API used by the rest of PETSc and by users.

      6:       These routines use a private API that is not used elsewhere in PETSc and is not
      7:       accessible to users. The private API is defined in logimpl.h and the utils directory.

      9:       ***

     11:       This file, and only this file, is for functions that interact with the global logging state
     12: */
     13: #include <petsc/private/logimpl.h>
     14: #include <petsc/private/loghandlerimpl.h>
     15: #include <petsctime.h>
     16: #include <petscviewer.h>
     17: #include <petscdevice.h>
     18: #include <petsc/private/deviceimpl.h>

     20: #if defined(PETSC_HAVE_THREADSAFETY)

     22: PetscInt           petsc_log_gid = -1; /* Global threadId counter */
     23: PETSC_TLS PetscInt petsc_log_tid = -1; /* Local threadId */

     25: /* shared variables */
     26: PetscSpinlock PetscLogSpinLock;

     28: PetscInt PetscLogGetTid(void)
     29: {
     30:   if (petsc_log_tid < 0) {
     31:     PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
     32:     petsc_log_tid = ++petsc_log_gid;
     33:     PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
     34:   }
     35:   return petsc_log_tid;
     36: }

     38: #endif

     40: /* Global counters */
     41: PetscLogDouble petsc_BaseTime        = 0.0;
     42: PetscLogDouble petsc_TotalFlops      = 0.0; /* The number of flops */
     43: PetscLogDouble petsc_send_ct         = 0.0; /* The number of sends */
     44: PetscLogDouble petsc_recv_ct         = 0.0; /* The number of receives */
     45: PetscLogDouble petsc_send_len        = 0.0; /* The total length of all sent messages */
     46: PetscLogDouble petsc_recv_len        = 0.0; /* The total length of all received messages */
     47: PetscLogDouble petsc_isend_ct        = 0.0; /* The number of immediate sends */
     48: PetscLogDouble petsc_irecv_ct        = 0.0; /* The number of immediate receives */
     49: PetscLogDouble petsc_isend_len       = 0.0; /* The total length of all immediate send messages */
     50: PetscLogDouble petsc_irecv_len       = 0.0; /* The total length of all immediate receive messages */
     51: PetscLogDouble petsc_wait_ct         = 0.0; /* The number of waits */
     52: PetscLogDouble petsc_wait_any_ct     = 0.0; /* The number of anywaits */
     53: PetscLogDouble petsc_wait_all_ct     = 0.0; /* The number of waitalls */
     54: PetscLogDouble petsc_sum_of_waits_ct = 0.0; /* The total number of waits */
     55: PetscLogDouble petsc_allreduce_ct    = 0.0; /* The number of reductions */
     56: PetscLogDouble petsc_gather_ct       = 0.0; /* The number of gathers and gathervs */
     57: PetscLogDouble petsc_scatter_ct      = 0.0; /* The number of scatters and scattervs */

     59: /* Thread Local storage */
     60: PETSC_TLS PetscLogDouble petsc_TotalFlops_th      = 0.0;
     61: PETSC_TLS PetscLogDouble petsc_send_ct_th         = 0.0;
     62: PETSC_TLS PetscLogDouble petsc_recv_ct_th         = 0.0;
     63: PETSC_TLS PetscLogDouble petsc_send_len_th        = 0.0;
     64: PETSC_TLS PetscLogDouble petsc_recv_len_th        = 0.0;
     65: PETSC_TLS PetscLogDouble petsc_isend_ct_th        = 0.0;
     66: PETSC_TLS PetscLogDouble petsc_irecv_ct_th        = 0.0;
     67: PETSC_TLS PetscLogDouble petsc_isend_len_th       = 0.0;
     68: PETSC_TLS PetscLogDouble petsc_irecv_len_th       = 0.0;
     69: PETSC_TLS PetscLogDouble petsc_wait_ct_th         = 0.0;
     70: PETSC_TLS PetscLogDouble petsc_wait_any_ct_th     = 0.0;
     71: PETSC_TLS PetscLogDouble petsc_wait_all_ct_th     = 0.0;
     72: PETSC_TLS PetscLogDouble petsc_sum_of_waits_ct_th = 0.0;
     73: PETSC_TLS PetscLogDouble petsc_allreduce_ct_th    = 0.0;
     74: PETSC_TLS PetscLogDouble petsc_gather_ct_th       = 0.0;
     75: PETSC_TLS PetscLogDouble petsc_scatter_ct_th      = 0.0;

     77: PetscLogDouble petsc_ctog_ct        = 0.0; /* The total number of CPU to GPU copies */
     78: PetscLogDouble petsc_gtoc_ct        = 0.0; /* The total number of GPU to CPU copies */
     79: PetscLogDouble petsc_ctog_sz        = 0.0; /* The total size of CPU to GPU copies */
     80: PetscLogDouble petsc_gtoc_sz        = 0.0; /* The total size of GPU to CPU copies */
     81: PetscLogDouble petsc_ctog_ct_scalar = 0.0; /* The total number of CPU to GPU copies */
     82: PetscLogDouble petsc_gtoc_ct_scalar = 0.0; /* The total number of GPU to CPU copies */
     83: PetscLogDouble petsc_ctog_sz_scalar = 0.0; /* The total size of CPU to GPU copies */
     84: PetscLogDouble petsc_gtoc_sz_scalar = 0.0; /* The total size of GPU to CPU copies */
     85: PetscLogDouble petsc_gflops         = 0.0; /* The flops done on a GPU */
     86: PetscLogDouble petsc_gtime          = 0.0; /* The time spent on a GPU */
     87: PetscLogDouble petsc_genergy        = 0.0; /* The energy (estimated with power*gtime) consumed on a GPU */
     88: PetscLogDouble petsc_genergy_meter  = 0.0; /* Readings from the energy meter on a GPU */

     90: PETSC_TLS PetscLogDouble petsc_ctog_ct_th        = 0.0;
     91: PETSC_TLS PetscLogDouble petsc_gtoc_ct_th        = 0.0;
     92: PETSC_TLS PetscLogDouble petsc_ctog_sz_th        = 0.0;
     93: PETSC_TLS PetscLogDouble petsc_gtoc_sz_th        = 0.0;
     94: PETSC_TLS PetscLogDouble petsc_ctog_ct_scalar_th = 0.0;
     95: PETSC_TLS PetscLogDouble petsc_gtoc_ct_scalar_th = 0.0;
     96: PETSC_TLS PetscLogDouble petsc_ctog_sz_scalar_th = 0.0;
     97: PETSC_TLS PetscLogDouble petsc_gtoc_sz_scalar_th = 0.0;
     98: PETSC_TLS PetscLogDouble petsc_gflops_th         = 0.0;
     99: PETSC_TLS PetscLogDouble petsc_gtime_th          = 0.0;

    101: PetscBool PetscLogMemory = PETSC_FALSE;
    102: PetscBool PetscLogSyncOn = PETSC_FALSE;

    104: PetscBool PetscLogGpuTimeFlag        = PETSC_FALSE;
    105: PetscBool PetscLogGpuEnergyFlag      = PETSC_FALSE;
    106: PetscBool PetscLogGpuEnergyMeterFlag = PETSC_FALSE;

    108: PetscInt PetscLogNumViewersCreated   = 0;
    109: PetscInt PetscLogNumViewersDestroyed = 0;

    111: PetscLogState petsc_log_state = NULL;

    113: #define PETSC_LOG_HANDLER_HOT_BLANK {NULL, NULL, NULL, NULL, NULL, NULL}

    115: PetscLogHandlerHot PetscLogHandlers[PETSC_LOG_HANDLER_MAX] = {
    116:   PETSC_LOG_HANDLER_HOT_BLANK,
    117:   PETSC_LOG_HANDLER_HOT_BLANK,
    118:   PETSC_LOG_HANDLER_HOT_BLANK,
    119:   PETSC_LOG_HANDLER_HOT_BLANK,
    120: };

    122: #undef PETSC_LOG_HANDLERS_HOT_BLANK

    124: #if defined(PETSC_USE_LOG)
    125: #include <../src/sys/logging/handler/impls/default/logdefault.h>

    127:   #if defined(PETSC_HAVE_THREADSAFETY)
    128: /*@
    129:   PetscAddLogDouble - Atomically add a `PetscLogDouble` value to both a global counter and its per-thread counterpart

    131:   Not Collective; No Fortran Support

    133:   Input Parameters:
    134: + tot    - pointer to the global counter to update
    135: . tot_th - pointer to the per-thread counter to update
    136: - value  - the value to add to both counters

    138:   Level: developer

    140:   Note:
    141:   When PETSc is built without thread safety this is a fast macro that performs the same update without locking.

    143: .seealso: `PetscAddLogDoubleCnt()`, `PetscLogFlops()`, `PetscLogDouble`
    144: @*/
    145: PetscErrorCode PetscAddLogDouble(PetscLogDouble *tot, PetscLogDouble *tot_th, PetscLogDouble value)
    146: {
    147:   *tot_th += value;
    148:   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
    149:   *tot += value;
    150:   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
    151:   return PETSC_SUCCESS;
    152: }

    154: /*@
    155:   PetscAddLogDoubleCnt - Atomically update both a count pair and a size pair of `PetscLogDouble` counters (global and per-thread)

    157:   Not Collective; No Fortran Support

    159:   Input Parameters:
    160: + cnt    - pointer to the global count counter to increment by one
    161: . tot    - pointer to the global size counter to update
    162: . cnt_th - pointer to the per-thread count counter to increment by one
    163: . tot_th - pointer to the per-thread size counter to update
    164: - value  - the size value to add to the size counters

    166:   Level: developer

    168: .seealso: `PetscAddLogDouble()`, `PetscLogFlops()`, `PetscLogDouble`
    169: @*/
    170: PetscErrorCode PetscAddLogDoubleCnt(PetscLogDouble *cnt, PetscLogDouble *tot, PetscLogDouble *cnt_th, PetscLogDouble *tot_th, PetscLogDouble value)
    171: {
    172:   *cnt_th = *cnt_th + 1;
    173:   *tot_th += value;
    174:   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
    175:   *tot += (PetscLogDouble)value;
    176:   *cnt += *cnt + 1;
    177:   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
    178:   return PETSC_SUCCESS;
    179: }

    181:   #endif

    183: static PetscErrorCode PetscLogTryGetHandler(PetscLogHandlerType type, PetscLogHandler *handler)
    184: {
    185:   PetscFunctionBegin;
    186:   PetscAssertPointer(handler, 2);
    187:   *handler = NULL;
    188:   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    189:     PetscLogHandler h = PetscLogHandlers[i].handler;
    190:     if (h) {
    191:       PetscBool match;

    193:       PetscCall(PetscObjectTypeCompare((PetscObject)h, type, &match));
    194:       if (match) {
    195:         *handler = PetscLogHandlers[i].handler;
    196:         PetscFunctionReturn(PETSC_SUCCESS);
    197:       }
    198:     }
    199:   }
    200:   PetscFunctionReturn(PETSC_SUCCESS);
    201: }

    203: /*@
    204:   PetscLogGetDefaultHandler - Get the default log handler if it is running.

    206:   Not collective

    208:   Output Parameter:
    209: . handler - the default `PetscLogHandler`, or `NULL` if it is not running.

    211:   Level: developer

    213:   Notes:
    214:   The default handler is started with `PetscLogDefaultBegin()`,
    215:   if the options flags `-log_all` or `-log_view` is given without arguments,
    216:   or for `-log_view :output:format` if `format` is not `ascii_xml` or `ascii_flamegraph`.

    218: .seealso: [](ch_profiling)
    219: @*/
    220: PetscErrorCode PetscLogGetDefaultHandler(PetscLogHandler *handler)
    221: {
    222:   PetscFunctionBegin;
    223:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, handler));
    224:   PetscFunctionReturn(PETSC_SUCCESS);
    225: }

    227: static PetscErrorCode PetscLogGetHandler(PetscLogHandlerType type, PetscLogHandler *handler)
    228: {
    229:   PetscFunctionBegin;
    230:   PetscAssertPointer(handler, 2);
    231:   PetscCall(PetscLogTryGetHandler(type, handler));
    232:   PetscCheck(*handler != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "A PetscLogHandler of type %s has not been started.", type);
    233:   PetscFunctionReturn(PETSC_SUCCESS);
    234: }

    236: /*@
    237:   PetscLogGetState - Get the `PetscLogState` for PETSc's global logging, used
    238:   by all default log handlers (`PetscLogDefaultBegin()`,
    239:   `PetscLogNestedBegin()`, `PetscLogTraceBegin()`, `PetscLogMPEBegin()`,
    240:   `PetscLogPerfstubsBegin()`).

    242:   Collective on `PETSC_COMM_WORLD`

    244:   Output Parameter:
    245: . state - The `PetscLogState` changed by registrations (such as
    246:           `PetscLogEventRegister()`) and actions (such as `PetscLogEventBegin()` or
    247:           `PetscLogStagePush()`), or `NULL` if logging is not active

    249:   Level: developer

    251: .seealso: [](ch_profiling), `PetscLogState`
    252: @*/
    253: PetscErrorCode PetscLogGetState(PetscLogState *state)
    254: {
    255:   PetscFunctionBegin;
    256:   PetscAssertPointer(state, 1);
    257:   *state = petsc_log_state;
    258:   PetscFunctionReturn(PETSC_SUCCESS);
    259: }

    261: static PetscErrorCode PetscLogHandlerCopyToHot(PetscLogHandler h, PetscLogHandlerHot *hot)
    262: {
    263:   PetscFunctionBegin;
    264:   hot->handler       = h;
    265:   hot->eventBegin    = h->ops->eventbegin;
    266:   hot->eventEnd      = h->ops->eventend;
    267:   hot->eventSync     = h->ops->eventsync;
    268:   hot->objectCreate  = h->ops->objectcreate;
    269:   hot->objectDestroy = h->ops->objectdestroy;
    270:   PetscFunctionReturn(PETSC_SUCCESS);
    271: }

    273: /*@
    274:   PetscLogHandlerStart - Connect a log handler to PETSc's global logging stream and state.

    276:   Logically collective

    278:   Input Parameters:
    279: . h - a `PetscLogHandler`

    281:   Level: developer

    283:   Notes:
    284:   Users should only need this if they create their own log handlers: handlers that are started
    285:   from the command line (such as `-log_view` and `-log_trace`) or from a function like
    286:   `PetscLogNestedBegin()` will automatically be started.

    288:   There is a limit of `PESC_LOG_HANDLER_MAX` handlers that can be active at one time.

    290:   To disconnect a handler from the global stream call `PetscLogHandlerStop()`.

    292:   When a log handler is started, stages that have already been pushed with `PetscLogStagePush()`,
    293:   will be pushed for the new log handler, but it will not be informed of any events that are
    294:   in progress.  It is recommended to start any user-defined log handlers immediately following
    295:   `PetscInitialize()`  before any user-defined stages are pushed.

    297: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogState`, `PetscLogHandlerStop()`, `PetscInitialize()`
    298: @*/
    299: PetscErrorCode PetscLogHandlerStart(PetscLogHandler h)
    300: {
    301:   PetscFunctionBegin;
    302:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    303:     if (PetscLogHandlers[i].handler == h) PetscFunctionReturn(PETSC_SUCCESS);
    304:   }
    305:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    306:     if (PetscLogHandlers[i].handler == NULL) {
    307:       PetscCall(PetscObjectReference((PetscObject)h));
    308:       PetscCall(PetscLogHandlerCopyToHot(h, &PetscLogHandlers[i]));
    309:       if (petsc_log_state) {
    310:         PetscLogStage stack_height;
    311:         PetscIntStack orig_stack, temp_stack;

    313:         PetscCall(PetscLogHandlerSetState(h, petsc_log_state));
    314:         stack_height = petsc_log_state->stage_stack->top + 1;
    315:         PetscCall(PetscIntStackCreate(&temp_stack));
    316:         orig_stack                     = petsc_log_state->stage_stack;
    317:         petsc_log_state->stage_stack   = temp_stack;
    318:         petsc_log_state->current_stage = -1;
    319:         for (int s = 0; s < stack_height; s++) {
    320:           PetscLogStage stage = orig_stack->stack[s];
    321:           PetscCall(PetscLogHandlerStagePush(h, stage));
    322:           PetscCall(PetscIntStackPush(temp_stack, stage));
    323:           petsc_log_state->current_stage = stage;
    324:         }
    325:         PetscCall(PetscIntStackDestroy(temp_stack));
    326:         petsc_log_state->stage_stack = orig_stack;
    327:       }
    328:       PetscFunctionReturn(PETSC_SUCCESS);
    329:     }
    330:   }
    331:   SETERRQ(PetscObjectComm((PetscObject)h), PETSC_ERR_ARG_WRONGSTATE, "%d log handlers already started, cannot start another", PETSC_LOG_HANDLER_MAX);
    332:   PetscFunctionReturn(PETSC_SUCCESS);
    333: }

    335: /*@
    336:   PetscLogHandlerStop - Disconnect a log handler from PETSc's global logging stream.

    338:   Logically collective

    340:   Input Parameters:
    341: . h - a `PetscLogHandler`

    343:   Level: developer

    345:   Note:
    346:   After `PetscLogHandlerStop()`, the handler can still access the global logging state
    347:   with `PetscLogHandlerGetState()`, so that it can access the registry when post-processing
    348:   (for instance, in `PetscLogHandlerView()`),

    350:   When a log handler is stopped, the remaining stages will be popped before it is
    351:   disconnected from the log stream.

    353: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogState`, `PetscLogHandlerStart()`
    354: @*/
    355: PetscErrorCode PetscLogHandlerStop(PetscLogHandler h)
    356: {
    357:   PetscFunctionBegin;
    358:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    359:     if (PetscLogHandlers[i].handler == h) {
    360:       if (petsc_log_state) {
    361:         PetscLogState state;
    362:         PetscLogStage stack_height;
    363:         PetscIntStack orig_stack, temp_stack;

    365:         PetscCall(PetscLogHandlerGetState(h, &state));
    366:         PetscCheck(state == petsc_log_state, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "Called PetscLogHandlerStop() for a PetscLogHander that was not started.");
    367:         stack_height = petsc_log_state->stage_stack->top + 1;
    368:         PetscCall(PetscIntStackCreate(&temp_stack));
    369:         orig_stack                   = petsc_log_state->stage_stack;
    370:         petsc_log_state->stage_stack = temp_stack;
    371:         for (int s = 0; s < stack_height; s++) {
    372:           PetscLogStage stage = orig_stack->stack[s];

    374:           PetscCall(PetscIntStackPush(temp_stack, stage));
    375:         }
    376:         for (int s = 0; s < stack_height; s++) {
    377:           PetscLogStage stage;
    378:           PetscBool     empty;

    380:           PetscCall(PetscIntStackPop(temp_stack, &stage));
    381:           PetscCall(PetscIntStackEmpty(temp_stack, &empty));
    382:           if (!empty) PetscCall(PetscIntStackTop(temp_stack, &petsc_log_state->current_stage));
    383:           else petsc_log_state->current_stage = -1;
    384:           PetscCall(PetscLogHandlerStagePop(h, stage));
    385:         }
    386:         PetscCall(PetscIntStackDestroy(temp_stack));
    387:         petsc_log_state->stage_stack = orig_stack;
    388:         PetscCall(PetscIntStackTop(petsc_log_state->stage_stack, &petsc_log_state->current_stage));
    389:       }
    390:       PetscCall(PetscArrayzero(&PetscLogHandlers[i], 1));
    391:       PetscCall(PetscObjectDereference((PetscObject)h));
    392:     }
    393:   }
    394:   PetscFunctionReturn(PETSC_SUCCESS);
    395: }

    397: /*@
    398:   PetscLogIsActive - Check if logging (profiling) is currently in progress.

    400:   Not Collective

    402:   Output Parameter:
    403: . isActive - `PETSC_TRUE` if logging is in progress, `PETSC_FALSE` otherwise

    405:   Level: beginner

    407: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`
    408: @*/
    409: PetscErrorCode PetscLogIsActive(PetscBool *isActive)
    410: {
    411:   PetscFunctionBegin;
    412:   *isActive = PETSC_FALSE;
    413:   if (petsc_log_state) {
    414:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    415:       if (PetscLogHandlers[i].handler) {
    416:         *isActive = PETSC_TRUE;
    417:         PetscFunctionReturn(PETSC_SUCCESS);
    418:       }
    419:     }
    420:   }
    421:   PetscFunctionReturn(PETSC_SUCCESS);
    422: }

    424: PETSC_UNUSED static PetscErrorCode PetscLogEventBeginIsActive(PetscBool *isActive)
    425: {
    426:   PetscFunctionBegin;
    427:   *isActive = PETSC_FALSE;
    428:   if (petsc_log_state) {
    429:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    430:       if (PetscLogHandlers[i].eventBegin) {
    431:         *isActive = PETSC_TRUE;
    432:         PetscFunctionReturn(PETSC_SUCCESS);
    433:       }
    434:     }
    435:   }
    436:   PetscFunctionReturn(PETSC_SUCCESS);
    437: }

    439: PETSC_UNUSED static PetscErrorCode PetscLogEventEndIsActive(PetscBool *isActive)
    440: {
    441:   PetscFunctionBegin;
    442:   *isActive = PETSC_FALSE;
    443:   if (petsc_log_state) {
    444:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    445:       if (PetscLogHandlers[i].eventEnd) {
    446:         *isActive = PETSC_TRUE;
    447:         PetscFunctionReturn(PETSC_SUCCESS);
    448:       }
    449:     }
    450:   }
    451:   PetscFunctionReturn(PETSC_SUCCESS);
    452: }

    454: PETSC_INTERN PetscErrorCode PetscLogTypeBegin(PetscLogHandlerType type)
    455: {
    456:   PetscLogHandler handler;

    458:   PetscFunctionBegin;
    459:   PetscCall(PetscLogTryGetHandler(type, &handler));
    460:   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
    461:   PetscCall(PetscLogHandlerCreate(PETSC_COMM_WORLD, &handler));
    462:   PetscCall(PetscLogHandlerSetType(handler, type));
    463:   PetscCall(PetscLogHandlerStart(handler));
    464:   PetscCall(PetscLogHandlerDestroy(&handler));
    465:   PetscFunctionReturn(PETSC_SUCCESS);
    466: }

    468: /*@
    469:   PetscLogDefaultBegin - Turns on logging (profiling) of PETSc code using the default log handler (profiler). This logs time, flop
    470:   rates, and object creation and should not slow programs down too much.

    472:   Logically Collective on `PETSC_COMM_WORLD`

    474:   Options Database Key:
    475: . -log_view [viewertype:filename:viewerformat] - Prints summary of flop and timing (profiling) information to the
    476:                                                  screen (for PETSc configured with `--with-log=1` (which is the default)).
    477:                                                  This option must be provided before `PetscInitialize()`.

    479:   Example Usage:
    480: .vb
    481:       PetscInitialize(...);
    482:       PetscLogDefaultBegin();
    483:        ... code ...
    484:       PetscLogView(viewer); or PetscLogDump();
    485:       PetscFinalize();
    486: .ve

    488:   Level: advanced

    490:   Notes:
    491:   `PetscLogView()` or `PetscLogDump()` actually cause the printing of
    492:   the logging information.

    494:   This routine may be called more than once.

    496:   To provide the `-log_view` option in your source code you must call  PetscCall(PetscOptionsSetValue(NULL, "-log_view", NULL));
    497:   before you call `PetscInitialize()`

    499: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`
    500: @*/
    501: PetscErrorCode PetscLogDefaultBegin(void)
    502: {
    503:   PetscFunctionBegin;
    504:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERDEFAULT));
    505:   PetscFunctionReturn(PETSC_SUCCESS);
    506: }

    508: /*@C
    509:   PetscLogTraceBegin - Begins trace logging.  Every time a PETSc event
    510:   begins or ends, the event name is printed.

    512:   Logically Collective on `PETSC_COMM_WORLD`, No Fortran Support

    514:   Input Parameter:
    515: . file - The file to print trace in (e.g. stdout)

    517:   Options Database Key:
    518: . -log_trace [filename] - Begins `PetscLogTraceBegin()`

    520:   Level: intermediate

    522:   Notes:
    523:   `PetscLogTraceBegin()` prints the processor number, the execution time (sec),
    524:   then "Event begin:" or "Event end:" followed by the event name.

    526:   `PetscLogTraceBegin()` allows tracing of all PETSc calls, which is useful
    527:   to determine where a program is hanging without running in the
    528:   debugger.  Can be used in conjunction with the -info option.

    530: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogDefaultBegin()`
    531: @*/
    532: PetscErrorCode PetscLogTraceBegin(FILE *file)
    533: {
    534:   PetscLogHandler handler;

    536:   PetscFunctionBegin;
    537:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERTRACE, &handler));
    538:   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
    539:   PetscCall(PetscLogHandlerCreateTrace(PETSC_COMM_WORLD, file, &handler));
    540:   PetscCall(PetscLogHandlerStart(handler));
    541:   PetscCall(PetscLogHandlerDestroy(&handler));
    542:   PetscFunctionReturn(PETSC_SUCCESS);
    543: }

    545: PETSC_INTERN PetscErrorCode PetscLogHandlerCreate_Nested(MPI_Comm, PetscLogHandler *);

    547: /*@
    548:   PetscLogNestedBegin - Turns on nested logging of objects and events. This logs flop
    549:   rates and object creation and should not slow programs down too much.

    551:   Logically Collective on `PETSC_COMM_WORLD`, No Fortran Support

    553:   Options Database Keys:
    554: . -log_view :filename.xml:ascii_xml - Prints an XML summary of flop and timing information to the file

    556:   Example Usage:
    557: .vb
    558:       PetscInitialize(...);
    559:       PetscLogNestedBegin();
    560:        ... code ...
    561:       PetscLogView(viewer);
    562:       PetscFinalize();
    563: .ve

    565:   Level: advanced

    567: .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`
    568: @*/
    569: PetscErrorCode PetscLogNestedBegin(void)
    570: {
    571:   PetscFunctionBegin;
    572:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERNESTED));
    573:   PetscFunctionReturn(PETSC_SUCCESS);
    574: }

    576: /*@C
    577:   PetscLogLegacyCallbacksBegin - Create and start a log handler from callbacks
    578:   matching the now deprecated function pointers `PetscLogPLB`, `PetscLogPLE`,
    579:   `PetscLogPHC`, `PetscLogPHD`.

    581:   Logically Collective on `PETSC_COMM_WORLD`

    583:   Input Parameters:
    584: + PetscLogPLB - A callback that will be executed by `PetscLogEventBegin()` (or `NULL`)
    585: . PetscLogPLE - A callback that will be executed by `PetscLogEventEnd()` (or `NULL`)
    586: . PetscLogPHC - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)
    587: - PetscLogPHD - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)

    589:   Calling sequence of `PetscLogPLB`:
    590: + e  - a `PetscLogEvent` that is beginning
    591: . _i - deprecated, unused
    592: . o1 - a `PetscObject` associated with `e` (or `NULL`)
    593: . o2 - a `PetscObject` associated with `e` (or `NULL`)
    594: . o3 - a `PetscObject` associated with `e` (or `NULL`)
    595: - o4 - a `PetscObject` associated with `e` (or `NULL`)

    597:   Calling sequence of `PetscLogPLE`:
    598: + e  - a `PetscLogEvent` that is beginning
    599: . _i - deprecated, unused
    600: . o1 - a `PetscObject` associated with `e` (or `NULL`)
    601: . o2 - a `PetscObject` associated with `e` (or `NULL`)
    602: . o3 - a `PetscObject` associated with `e` (or `NULL`)
    603: - o4 - a `PetscObject` associated with `e` (or `NULL`)

    605:   Calling sequence of `PetscLogPHC`:
    606: . o - a `PetscObject` that has just been created

    608:   Calling sequence of `PetscLogPHD`:
    609: . o - a `PetscObject` that is about to be destroyed

    611:   Level: advanced

    613:   Notes:
    614:   This is for transitioning from the deprecated function `PetscLogSet()` and should not be used in new code.

    616:   This should help migrate external log handlers to use `PetscLogHandler`, but
    617:   callbacks that depend on the deprecated `PetscLogStage` datatype will have to be
    618:   updated.

    620: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogHandlerStart()`, `PetscLogState`
    621: @*/
    622: PetscErrorCode PetscLogLegacyCallbacksBegin(PetscErrorCode (*PetscLogPLB)(PetscLogEvent e, int _i, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4), PetscErrorCode (*PetscLogPLE)(PetscLogEvent e, int _i, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4), PetscErrorCode (*PetscLogPHC)(PetscObject o), PetscErrorCode (*PetscLogPHD)(PetscObject o))
    623: {
    624:   PetscLogHandler handler;

    626:   PetscFunctionBegin;
    627:   PetscCall(PetscLogHandlerCreateLegacy(PETSC_COMM_WORLD, PetscLogPLB, PetscLogPLE, PetscLogPHC, PetscLogPHD, &handler));
    628:   PetscCall(PetscLogHandlerStart(handler));
    629:   PetscCall(PetscLogHandlerDestroy(&handler));
    630:   PetscFunctionReturn(PETSC_SUCCESS);
    631: }

    633:   #if defined(PETSC_HAVE_MPE)
    634:     #include <mpe.h>
    635: static PetscBool PetscBeganMPE = PETSC_FALSE;
    636:   #endif

    638: /*@C
    639:   PetscLogMPEBegin - Turns on MPE logging of events. This creates large log files and slows the
    640:   program down.

    642:   Collective on `PETSC_COMM_WORLD`, No Fortran Support

    644:   Options Database Key:
    645: . -log_mpe - Prints extensive log information

    647:   Level: advanced

    649:   Note:
    650:   A related routine is `PetscLogDefaultBegin()` (with the options key `-log_view`), which is
    651:   intended for production runs since it logs only flop rates and object creation (and should
    652:   not significantly slow the programs).

    654: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogDefaultBegin()`, `PetscLogEventActivate()`,
    655:           `PetscLogEventDeactivate()`
    656: @*/
    657: PetscErrorCode PetscLogMPEBegin(void)
    658: {
    659:   PetscFunctionBegin;
    660:   #if defined(PETSC_HAVE_MPE)
    661:   /* Do MPE initialization */
    662:   if (!MPE_Initialized_logging()) { /* This function exists in mpich 1.1.2 and higher */
    663:     PetscCall(PetscInfo(0, "Initializing MPE.\n"));
    664:     PetscCall(MPE_Init_log());

    666:     PetscBeganMPE = PETSC_TRUE;
    667:   } else {
    668:     PetscCall(PetscInfo(0, "MPE already initialized. Not attempting to reinitialize.\n"));
    669:   }
    670:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERMPE));
    671:   #else
    672:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
    673:   #endif
    674:   PetscFunctionReturn(PETSC_SUCCESS);
    675: }

    677:   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
    678: #include <../src/sys/perfstubs/timer.h>
    679:   #endif

    681: /*@C
    682:   PetscLogPerfstubsBegin - Turns on logging of events using the perfstubs interface.

    684:   Collective on `PETSC_COMM_WORLD`, No Fortran Support

    686:   Options Database Key:
    687: . -log_perfstubs - use an external log handler through the perfstubs interface

    689:   Level: advanced

    691: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogEventActivate()`
    692: @*/
    693: PetscErrorCode PetscLogPerfstubsBegin(void)
    694: {
    695:   PetscFunctionBegin;
    696:   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
    697:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERPERFSTUBS));
    698:   #else
    699:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without perfstubs support, reconfigure with --with-tau-perfstubs");
    700:   #endif
    701:   PetscFunctionReturn(PETSC_SUCCESS);
    702: }

    704: /*@
    705:   PetscLogActions - Determines whether actions are logged for the default log handler.

    707:   Not Collective

    709:   Input Parameter:
    710: . flag - `PETSC_TRUE` if actions are to be logged

    712:   Options Database Key:
    713: + -log_exclude_actions - (deprecated) Does nothing
    714: - -log_include_actions - Turn on action logging

    716:   Level: intermediate

    718:   Note:
    719:   Logging of actions continues to consume more memory as the program
    720:   runs. Long running programs should consider turning this feature off.

    722: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogGetDefaultHandler()`
    723: @*/
    724: PetscErrorCode PetscLogActions(PetscBool flag)
    725: {
    726:   PetscFunctionBegin;
    727:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    728:     PetscLogHandler h = PetscLogHandlers[i].handler;

    730:     if (h) PetscCall(PetscLogHandlerSetLogActions(h, flag));
    731:   }
    732:   PetscFunctionReturn(PETSC_SUCCESS);
    733: }

    735: /*@
    736:   PetscLogObjects - Determines whether objects are logged for the graphical viewer.

    738:   Not Collective

    740:   Input Parameter:
    741: . flag - `PETSC_TRUE` if objects are to be logged

    743:   Options Database Key:
    744: + -log_exclude_objects - (deprecated) Does nothing
    745: - -log_include_objects - Turns on object logging

    747:   Level: intermediate

    749:   Note:
    750:   Logging of objects continues to consume more memory as the program
    751:   runs. Long running programs should consider turning this feature off.

    753: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogGetDefaultHandler()`
    754: @*/
    755: PetscErrorCode PetscLogObjects(PetscBool flag)
    756: {
    757:   PetscFunctionBegin;
    758:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    759:     PetscLogHandler h = PetscLogHandlers[i].handler;

    761:     if (h) PetscCall(PetscLogHandlerSetLogObjects(h, flag));
    762:   }
    763:   PetscFunctionReturn(PETSC_SUCCESS);
    764: }

    766: /*------------------------------------------------ Stage Functions --------------------------------------------------*/
    767: /*@
    768:   PetscLogStageRegister - Attaches a character string name to a logging stage.

    770:   Not Collective

    772:   Input Parameter:
    773: . sname - The name to associate with that stage

    775:   Output Parameter:
    776: . stage - The stage number or -1 if logging is not active (`PetscLogIsActive()`).

    778:   Level: intermediate

    780: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`
    781: @*/
    782: PetscErrorCode PetscLogStageRegister(const char sname[], PetscLogStage *stage)
    783: {
    784:   PetscLogState state;

    786:   PetscFunctionBegin;
    787:   *stage = -1;
    788:   PetscCall(PetscLogGetState(&state));
    789:   if (state) PetscCall(PetscLogStateStageRegister(state, sname, stage));
    790:   PetscFunctionReturn(PETSC_SUCCESS);
    791: }

    793: /*@
    794:   PetscLogStagePush - This function pushes a stage on the logging stack. Events started and stopped until `PetscLogStagePop()` will be associated with the stage

    796:   Not Collective

    798:   Input Parameter:
    799: . stage - The stage on which to log

    801:   Example Usage:
    802:   If the option -log_view is used to run the program containing the
    803:   following code, then 2 sets of summary data will be printed during
    804:   PetscFinalize().
    805: .vb
    806:       PetscInitialize(int *argc,char ***args,0,0);
    807:       [stage 0 of code]
    808:       PetscLogStagePush(1);
    809:       [stage 1 of code]
    810:       PetscLogStagePop();
    811:       PetscBarrier(...);
    812:       [more stage 0 of code]
    813:       PetscFinalize();
    814: .ve

    816:   Level: intermediate

    818:   Note:
    819:   Use `PetscLogStageRegister()` to register a stage.

    821: .seealso: [](ch_profiling), `PetscLogStagePop()`, `PetscLogStageRegister()`, `PetscBarrier()`
    822: @*/
    823: PetscErrorCode PetscLogStagePush(PetscLogStage stage)
    824: {
    825:   PetscLogState state;

    827:   PetscFunctionBegin;
    828:   PetscCall(PetscLogGetState(&state));
    829:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
    830:   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    831:     PetscLogHandler h = PetscLogHandlers[i].handler;
    832:     if (h) PetscCall(PetscLogHandlerStagePush(h, stage));
    833:   }
    834:   PetscCall(PetscLogStateStagePush(state, stage));
    835:   PetscFunctionReturn(PETSC_SUCCESS);
    836: }

    838: /*@
    839:   PetscLogStagePop - This function pops a stage from the logging stack that was pushed with `PetscLogStagePush()`

    841:   Not Collective

    843:   Example Usage:
    844:   If the option -log_view is used to run the program containing the
    845:   following code, then 2 sets of summary data will be printed during
    846:   PetscFinalize().
    847: .vb
    848:       PetscInitialize(int *argc,char ***args,0,0);
    849:       [stage 0 of code]
    850:       PetscLogStagePush(1);
    851:       [stage 1 of code]
    852:       PetscLogStagePop();
    853:       PetscBarrier(...);
    854:       [more stage 0 of code]
    855:       PetscFinalize();
    856: .ve

    858:   Level: intermediate

    860: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStageRegister()`, `PetscBarrier()`
    861: @*/
    862: PetscErrorCode PetscLogStagePop(void)
    863: {
    864:   PetscLogState state;
    865:   PetscLogStage current_stage;

    867:   PetscFunctionBegin;
    868:   PetscCall(PetscLogGetState(&state));
    869:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
    870:   current_stage = state->current_stage;
    871:   PetscCall(PetscLogStateStagePop(state));
    872:   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    873:     PetscLogHandler h = PetscLogHandlers[i].handler;
    874:     if (h) PetscCall(PetscLogHandlerStagePop(h, current_stage));
    875:   }
    876:   PetscFunctionReturn(PETSC_SUCCESS);
    877: }

    879: /*@
    880:   PetscLogStageSetActive - Sets if a stage is used for `PetscLogEventBegin()` and `PetscLogEventEnd()`.

    882:   Not Collective

    884:   Input Parameters:
    885: + stage    - The stage
    886: - isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)

    888:   Level: intermediate

    890:   Note:
    891:   If this is set to `PETSC_FALSE` the logging acts as if the stage did not exist

    893: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
    894: @*/
    895: PetscErrorCode PetscLogStageSetActive(PetscLogStage stage, PetscBool isActive)
    896: {
    897:   PetscLogState state;

    899:   PetscFunctionBegin;
    900:   PetscCall(PetscLogGetState(&state));
    901:   if (state) PetscCall(PetscLogStateStageSetActive(state, stage, isActive));
    902:   PetscFunctionReturn(PETSC_SUCCESS);
    903: }

    905: /*@
    906:   PetscLogStageGetActive - Checks if a stage is used for `PetscLogEventBegin()` and `PetscLogEventEnd()`.

    908:   Not Collective

    910:   Input Parameter:
    911: . stage - The stage

    913:   Output Parameter:
    914: . isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)

    916:   Level: intermediate

    918: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
    919: @*/
    920: PetscErrorCode PetscLogStageGetActive(PetscLogStage stage, PetscBool *isActive)
    921: {
    922:   PetscLogState state;

    924:   PetscFunctionBegin;
    925:   *isActive = PETSC_FALSE;
    926:   PetscCall(PetscLogGetState(&state));
    927:   if (state) PetscCall(PetscLogStateStageGetActive(state, stage, isActive));
    928:   PetscFunctionReturn(PETSC_SUCCESS);
    929: }

    931: /*@
    932:   PetscLogStageSetVisible - Determines stage visibility in `PetscLogView()`

    934:   Not Collective

    936:   Input Parameters:
    937: + stage     - The stage
    938: - isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)

    940:   Level: intermediate

    942:   Developer Notes:
    943:   Visibility only affects the default log handler in `PetscLogView()`: stages that are
    944:   set to invisible are suppressed from output.

    946: .seealso: [](ch_profiling), `PetscLogStageGetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
    947: @*/
    948: PetscErrorCode PetscLogStageSetVisible(PetscLogStage stage, PetscBool isVisible)
    949: {
    950:   PetscFunctionBegin;
    951:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    952:     PetscLogHandler h = PetscLogHandlers[i].handler;

    954:     if (h) PetscCall(PetscLogHandlerStageSetVisible(h, stage, isVisible));
    955:   }
    956:   PetscFunctionReturn(PETSC_SUCCESS);
    957: }

    959: /*@
    960:   PetscLogStageGetVisible - Returns stage visibility in `PetscLogView()`

    962:   Not Collective

    964:   Input Parameter:
    965: . stage - The stage

    967:   Output Parameter:
    968: . isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)

    970:   Level: intermediate

    972: .seealso: [](ch_profiling), `PetscLogStageSetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
    973: @*/
    974: PetscErrorCode PetscLogStageGetVisible(PetscLogStage stage, PetscBool *isVisible)
    975: {
    976:   PetscLogHandler handler;

    978:   PetscFunctionBegin;
    979:   *isVisible = PETSC_FALSE;
    980:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
    981:   if (handler) PetscCall(PetscLogHandlerStageGetVisible(handler, stage, isVisible));
    982:   PetscFunctionReturn(PETSC_SUCCESS);
    983: }

    985: /*@
    986:   PetscLogStageGetId - Returns the stage id when given the stage name.

    988:   Not Collective

    990:   Input Parameter:
    991: . name - The stage name

    993:   Output Parameter:
    994: . stage - The stage, , or -1 if no stage with that name exists

    996:   Level: intermediate

    998: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
    999: @*/
    1000: PetscErrorCode PetscLogStageGetId(const char name[], PetscLogStage *stage)
    1001: {
    1002:   PetscLogState state;

    1004:   PetscFunctionBegin;
    1005:   *stage = -1;
    1006:   PetscCall(PetscLogGetState(&state));
    1007:   if (state) PetscCall(PetscLogStateGetStageFromName(state, name, stage));
    1008:   PetscFunctionReturn(PETSC_SUCCESS);
    1009: }

    1011: /*@
    1012:   PetscLogStageGetName - Returns the stage name when given the stage id.

    1014:   Not Collective

    1016:   Input Parameter:
    1017: . stage - The stage

    1019:   Output Parameter:
    1020: . name - The stage name

    1022:   Level: intermediate

    1024: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
    1025: @*/
    1026: PetscErrorCode PetscLogStageGetName(PetscLogStage stage, const char *name[])
    1027: {
    1028:   PetscLogStageInfo stage_info;
    1029:   PetscLogState     state;

    1031:   PetscFunctionBegin;
    1032:   *name = NULL;
    1033:   PetscCall(PetscLogGetState(&state));
    1034:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
    1035:   PetscCall(PetscLogStateStageGetInfo(state, stage, &stage_info));
    1036:   *name = stage_info.name;
    1037:   PetscFunctionReturn(PETSC_SUCCESS);
    1038: }

    1040: /*------------------------------------------------ Event Functions --------------------------------------------------*/

    1042: /*@
    1043:   PetscLogEventRegister - Registers an event name for logging operations

    1045:   Not Collective

    1047:   Input Parameters:
    1048: + name    - The name associated with the event
    1049: - classid - The classid associated to the class for this event, obtain either with
    1050:            `PetscClassIdRegister()` or use a predefined one such as `KSP_CLASSID`, `SNES_CLASSID`, the predefined ones
    1051:            are only available in C code

    1053:   Output Parameter:
    1054: . event - The event id for use with `PetscLogEventBegin()` and `PetscLogEventEnd()`.

    1056:   Example Usage:
    1057: .vb
    1058:       PetscLogEvent USER_EVENT;
    1059:       PetscClassId classid;
    1060:       PetscLogDouble user_event_flops;
    1061:       PetscClassIdRegister("class name",&classid);
    1062:       PetscLogEventRegister("User event name",classid,&USER_EVENT);
    1063:       PetscLogEventBegin(USER_EVENT,0,0,0,0);
    1064:          [code segment to monitor]
    1065:          PetscLogFlops(user_event_flops);
    1066:       PetscLogEventEnd(USER_EVENT,0,0,0,0);
    1067: .ve

    1069:   Level: intermediate

    1071:   Notes:
    1072:   PETSc automatically logs library events if the code has been
    1073:   configured with --with-log (which is the default) and
    1074:   -log_view or -log_all is specified.  `PetscLogEventRegister()` is
    1075:   intended for logging user events to supplement this PETSc
    1076:   information.

    1078:   PETSc can gather data for use with the utilities Jumpshot
    1079:   (part of the MPICH distribution).  If PETSc has been compiled
    1080:   with flag -DPETSC_HAVE_MPE (MPE is an additional utility within
    1081:   MPICH), the user can employ another command line option, -log_mpe,
    1082:   to create a logfile, "mpe.log", which can be visualized
    1083:   Jumpshot.

    1085:   The classid is associated with each event so that classes of events
    1086:   can be disabled simultaneously, such as all matrix events. The user
    1087:   can either use an existing classid, such as `MAT_CLASSID`, or create
    1088:   their own as shown in the example.

    1090:   If an existing event with the same name exists, its event handle is
    1091:   returned instead of creating a new event.

    1093: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogFlops()`,
    1094:           `PetscLogEventActivate()`, `PetscLogEventDeactivate()`, `PetscClassIdRegister()`
    1095: @*/
    1096: PetscErrorCode PetscLogEventRegister(const char name[], PetscClassId classid, PetscLogEvent *event)
    1097: {
    1098:   PetscLogState state;

    1100:   PetscFunctionBegin;
    1101:   *event = -1;
    1102:   PetscCall(PetscLogGetState(&state));
    1103:   if (state) PetscCall(PetscLogStateEventRegister(state, name, classid, event));
    1104:   PetscFunctionReturn(PETSC_SUCCESS);
    1105: }

    1107: /*@
    1108:   PetscLogEventSetCollective - Indicates that a particular event is collective.

    1110:   Logically Collective

    1112:   Input Parameters:
    1113: + event      - The event id
    1114: - collective - `PetscBool` indicating whether a particular event is collective

    1116:   Level: developer

    1118:   Notes:
    1119:   New events returned from `PetscLogEventRegister()` are collective by default.

    1121:   Collective events are handled specially if the command line option `-log_sync` is used. In that case the logging saves information about
    1122:   two parts of the event; the time for all the MPI ranks to synchronize and then the time for the actual computation/communication
    1123:   to be performed. This option is useful to debug imbalance within the computations or communications.

    1125: .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogEventRegister()`
    1126: @*/
    1127: PetscErrorCode PetscLogEventSetCollective(PetscLogEvent event, PetscBool collective)
    1128: {
    1129:   PetscLogState state;

    1131:   PetscFunctionBegin;
    1132:   PetscCall(PetscLogGetState(&state));
    1133:   if (state) PetscCall(PetscLogStateEventSetCollective(state, event, collective));
    1134:   PetscFunctionReturn(PETSC_SUCCESS);
    1135: }

    1137: /*
    1138:   PetscLogClassSetActiveAll - Activate or inactivate logging for all events associated with a PETSc object class in every stage.

    1140:   Not Collective

    1142:   Input Parameters:
    1143: + classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
    1144: - isActive - if `PETSC_FALSE`, events associated with this class will not be send to log handlers.

    1146:   Level: developer

    1148: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`, `PetscLogEventActivateClass()`
    1149: */
    1150: static PetscErrorCode PetscLogClassSetActiveAll(PetscClassId classid, PetscBool isActive)
    1151: {
    1152:   PetscLogState state;

    1154:   PetscFunctionBegin;
    1155:   PetscCall(PetscLogGetState(&state));
    1156:   if (state) PetscCall(PetscLogStateClassSetActiveAll(state, classid, isActive));
    1157:   PetscFunctionReturn(PETSC_SUCCESS);
    1158: }

    1160: /*@
    1161:   PetscLogEventIncludeClass - Activates event logging for a PETSc object class in every stage.

    1163:   Not Collective

    1165:   Input Parameter:
    1166: . classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.

    1168:   Level: developer

    1170: .seealso: [](ch_profiling), `PetscLogEventActivateClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
    1171: @*/
    1172: PetscErrorCode PetscLogEventIncludeClass(PetscClassId classid)
    1173: {
    1174:   PetscFunctionBegin;
    1175:   PetscCall(PetscLogClassSetActiveAll(classid, PETSC_TRUE));
    1176:   PetscFunctionReturn(PETSC_SUCCESS);
    1177: }

    1179: /*@
    1180:   PetscLogEventExcludeClass - Deactivates event logging for a PETSc object class in every stage.

    1182:   Not Collective

    1184:   Input Parameter:
    1185: . classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.

    1187:   Level: developer

    1189:   Note:
    1190:   If a class is excluded then events associated with that class are not logged.

    1192: .seealso: [](ch_profiling), `PetscLogEventDeactivateClass()`, `PetscLogEventActivateClass()`, `PetscLogEventDeactivate()`, `PetscLogEventActivate()`
    1193: @*/
    1194: PetscErrorCode PetscLogEventExcludeClass(PetscClassId classid)
    1195: {
    1196:   PetscFunctionBegin;
    1197:   PetscCall(PetscLogClassSetActiveAll(classid, PETSC_FALSE));
    1198:   PetscFunctionReturn(PETSC_SUCCESS);
    1199: }

    1201: /*
    1202:   PetscLogEventSetActive - Activate or inactivate logging for an event in a given stage

    1204:   Not Collective

    1206:   Input Parameters:
    1207: + stage - A registered `PetscLogStage` (or `PETSC_DEFAULT` for the current stage)
    1208: . event - A `PetscLogEvent`
    1209: - isActive - If `PETSC_FALSE`, activity from this event (`PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogEventSync()`) will not be sent to log handlers during this stage

    1211:   Usage:
    1212: .vb
    1213:       PetscLogEventSetActive(VEC_SetValues, PETSC_FALSE);
    1214:         [code where you do not want to log VecSetValues()]
    1215:       PetscLogEventSetActive(VEC_SetValues, PETSC_TRUE);
    1216:         [code where you do want to log VecSetValues()]
    1217: .ve

    1219:   Level: advanced

    1221:   Note:
    1222:   The event may be either a pre-defined PETSc event (found in include/petsclog.h)
    1223:   or an event number obtained with `PetscLogEventRegister()`.

    1225: .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
    1226: */
    1227: static PetscErrorCode PetscLogEventSetActive(PetscLogStage stage, PetscLogEvent event, PetscBool isActive)
    1228: {
    1229:   PetscLogState state;

    1231:   PetscFunctionBegin;
    1232:   PetscCall(PetscLogGetState(&state));
    1233:   if (state) PetscCall(PetscLogStateEventSetActive(state, stage, event, isActive));
    1234:   PetscFunctionReturn(PETSC_SUCCESS);
    1235: }

    1237: /*@
    1238:   PetscLogEventActivate - Indicates that a particular event should be logged.

    1240:   Not Collective

    1242:   Input Parameter:
    1243: . event - The event id

    1245:   Example Usage:
    1246: .vb
    1247:       PetscLogEventDeactivate(VEC_SetValues);
    1248:         [code where you do not want to log VecSetValues()]
    1249:       PetscLogEventActivate(VEC_SetValues);
    1250:         [code where you do want to log VecSetValues()]
    1251: .ve

    1253:   Level: advanced

    1255:   Note:
    1256:   The event may be either a pre-defined PETSc event (found in include/petsclog.h)
    1257:   or an event number obtained with `PetscLogEventRegister()`.

    1259: .seealso: [](ch_profiling), `PetscLogEventDeactivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
    1260: @*/
    1261: PetscErrorCode PetscLogEventActivate(PetscLogEvent event)
    1262: {
    1263:   PetscFunctionBegin;
    1264:   PetscCall(PetscLogEventSetActive(PETSC_DEFAULT, event, PETSC_TRUE));
    1265:   PetscFunctionReturn(PETSC_SUCCESS);
    1266: }

    1268: /*@
    1269:   PetscLogEventDeactivate - Indicates that a particular event should not be logged.

    1271:   Not Collective

    1273:   Input Parameter:
    1274: . event - The event id

    1276:   Example Usage:
    1277: .vb
    1278:       PetscLogEventDeactivate(VEC_SetValues);
    1279:         [code where you do not want to log VecSetValues()]
    1280:       PetscLogEventActivate(VEC_SetValues);
    1281:         [code where you do want to log VecSetValues()]
    1282: .ve

    1284:   Level: advanced

    1286:   Note:
    1287:   The event may be either a pre-defined PETSc event (found in
    1288:   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).

    1290: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
    1291: @*/
    1292: PetscErrorCode PetscLogEventDeactivate(PetscLogEvent event)
    1293: {
    1294:   PetscFunctionBegin;
    1295:   PetscCall(PetscLogEventSetActive(PETSC_DEFAULT, event, PETSC_FALSE));
    1296:   PetscFunctionReturn(PETSC_SUCCESS);
    1297: }

    1299: /*@
    1300:   PetscLogEventDeactivatePush - Indicates that a particular event should not be logged until `PetscLogEventDeactivatePop()` is called

    1302:   Not Collective

    1304:   Input Parameter:
    1305: . event - The event id

    1307:   Example Usage:
    1308: .vb
    1309:       PetscLogEventDeactivatePush(VEC_SetValues);
    1310:         [code where you do not want to log VecSetValues()]
    1311:       PetscLogEventDeactivatePop(VEC_SetValues);
    1312:         [code where you do want to log VecSetValues()]
    1313: .ve

    1315:   Level: advanced

    1317:   Note:
    1318:   The event may be either a pre-defined PETSc event (found in
    1319:   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).

    1321:   PETSc's default log handler (`PetscLogDefaultBegin()`) respects this function because it can make the output of `PetscLogView()` easier to interpret, but other handlers (such as the nested handler, `PetscLogNestedBegin()`) ignore it because suppressing events is not helpful in their output formats.

    1323: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivate()`, `PetscLogEventDeactivatePop()`
    1324: @*/
    1325: PetscErrorCode PetscLogEventDeactivatePush(PetscLogEvent event)
    1326: {
    1327:   PetscFunctionBegin;
    1328:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    1329:     PetscLogHandler h = PetscLogHandlers[i].handler;

    1331:     if (h) PetscCall(PetscLogHandlerEventDeactivatePush(h, PETSC_DEFAULT, event));
    1332:   }
    1333:   PetscFunctionReturn(PETSC_SUCCESS);
    1334: }

    1336: /*@
    1337:   PetscLogEventDeactivatePop - Indicates that a particular event should again be logged after the logging was turned off with `PetscLogEventDeactivatePush()`

    1339:   Not Collective

    1341:   Input Parameter:
    1342: . event - The event id

    1344:   Example Usage:
    1345: .vb
    1346:       PetscLogEventDeactivatePush(VEC_SetValues);
    1347:         [code where you do not want to log VecSetValues()]
    1348:       PetscLogEventDeactivatePop(VEC_SetValues);
    1349:         [code where you do want to log VecSetValues()]
    1350: .ve

    1352:   Level: advanced

    1354:   Note:
    1355:   The event may be either a pre-defined PETSc event (found in
    1356:   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).

    1358: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`
    1359: @*/
    1360: PetscErrorCode PetscLogEventDeactivatePop(PetscLogEvent event)
    1361: {
    1362:   PetscFunctionBegin;
    1363:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    1364:     PetscLogHandler h = PetscLogHandlers[i].handler;

    1366:     if (h) PetscCall(PetscLogHandlerEventDeactivatePop(h, PETSC_DEFAULT, event));
    1367:   }
    1368:   PetscFunctionReturn(PETSC_SUCCESS);
    1369: }

    1371: /*@
    1372:   PetscLogEventSetActiveAll - Turns on logging of all events

    1374:   Not Collective

    1376:   Input Parameters:
    1377: + event    - The event id
    1378: - isActive - The activity flag determining whether the event is logged

    1380:   Level: advanced

    1382: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
    1383: @*/
    1384: PetscErrorCode PetscLogEventSetActiveAll(PetscLogEvent event, PetscBool isActive)
    1385: {
    1386:   PetscLogState state;

    1388:   PetscFunctionBegin;
    1389:   PetscCall(PetscLogGetState(&state));
    1390:   if (state) PetscCall(PetscLogStateEventSetActiveAll(state, event, isActive));
    1391:   PetscFunctionReturn(PETSC_SUCCESS);
    1392: }

    1394: /*
    1395:   PetscLogClassSetActive - Activates event logging for a PETSc object class for the current stage

    1397:   Not Collective

    1399:   Input Parameters:
    1400: + stage - A registered `PetscLogStage` (or `PETSC_DEFAULT` for the current stage)
    1401: . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
    1402: - isActive - If `PETSC_FALSE`, events associated with this class are not sent to log handlers.

    1404:   Level: developer

    1406: .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`
    1407: */
    1408: static PetscErrorCode PetscLogClassSetActive(PetscLogStage stage, PetscClassId classid, PetscBool isActive)
    1409: {
    1410:   PetscLogState state;

    1412:   PetscFunctionBegin;
    1413:   PetscCall(PetscLogGetState(&state));
    1414:   if (state) PetscCall(PetscLogStateClassSetActive(state, stage, classid, isActive));
    1415:   PetscFunctionReturn(PETSC_SUCCESS);
    1416: }

    1418: /*@
    1419:   PetscLogEventActivateClass - Activates event logging for a PETSc object class for the current stage

    1421:   Not Collective

    1423:   Input Parameter:
    1424: . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.

    1426:   Level: developer

    1428: .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
    1429: @*/
    1430: PetscErrorCode PetscLogEventActivateClass(PetscClassId classid)
    1431: {
    1432:   PetscFunctionBegin;
    1433:   PetscCall(PetscLogClassSetActive(PETSC_DEFAULT, classid, PETSC_TRUE));
    1434:   PetscFunctionReturn(PETSC_SUCCESS);
    1435: }

    1437: /*@
    1438:   PetscLogEventDeactivateClass - Deactivates event logging for a PETSc object class for the current stage

    1440:   Not Collective

    1442:   Input Parameter:
    1443: . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.

    1445:   Level: developer

    1447: .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventActivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
    1448: @*/
    1449: PetscErrorCode PetscLogEventDeactivateClass(PetscClassId classid)
    1450: {
    1451:   PetscFunctionBegin;
    1452:   PetscCall(PetscLogClassSetActive(PETSC_DEFAULT, classid, PETSC_FALSE));
    1453:   PetscFunctionReturn(PETSC_SUCCESS);
    1454: }

    1456: /*MC
    1457:   PetscLogEventSync - Synchronizes the beginning of a user event.

    1459:   Synopsis:
    1460: #include <petsclog.h>
    1461:   PetscErrorCode PetscLogEventSync(PetscLogEvent e, MPI_Comm comm)

    1463:   Collective

    1465:   Input Parameters:
    1466: + e    - `PetscLogEvent` obtained from `PetscLogEventRegister()`
    1467: - comm - an MPI communicator

    1469:   Example Usage:
    1470: .vb
    1471:   PetscLogEvent USER_EVENT;

    1473:   PetscLogEventRegister("User event", 0, &USER_EVENT);
    1474:   PetscLogEventSync(USER_EVENT, PETSC_COMM_WORLD);
    1475:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
    1476:   [code segment to monitor]
    1477:   PetscLogEventEnd(USER_EVENT, 0, 0, 0 , 0);
    1478: .ve

    1480:   Level: developer

    1482:   Note:
    1483:   This routine should be called only if there is not a `PetscObject` available to pass to
    1484:   `PetscLogEventBegin()`.

    1486: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`
    1487: M*/

    1489: /*MC
    1490:   PetscLogEventBegin - Logs the beginning of a user event.

    1492:   Synopsis:
    1493: #include <petsclog.h>
    1494:   PetscErrorCode PetscLogEventBegin(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)

    1496:   Not Collective

    1498:   Input Parameters:
    1499: + e  - `PetscLogEvent` obtained from `PetscLogEventRegister()`
    1500: . o1 - object associated with the event, or `NULL`
    1501: . o2 - object associated with the event, or `NULL`
    1502: . o3 - object associated with the event, or `NULL`
    1503: - o4 - object associated with the event, or `NULL`

    1505:   Fortran Synopsis:
    1506:   void PetscLogEventBegin(int e, PetscErrorCode ierr)

    1508:   Example Usage:
    1509: .vb
    1510:   PetscLogEvent USER_EVENT;

    1512:   PetscLogDouble user_event_flops;
    1513:   PetscLogEventRegister("User event",0, &USER_EVENT);
    1514:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
    1515:   [code segment to monitor]
    1516:   PetscLogFlops(user_event_flops);
    1517:   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
    1518: .ve

    1520:   Level: intermediate

    1522:   Developer Note:
    1523:   `PetscLogEventBegin()` and `PetscLogEventBegin()` return error codes instead of explicitly
    1524:   handling the errors that occur in the macro directly because other packages that use this
    1525:   macros have used them in their own functions or methods that do not return error codes and it
    1526:   would be disruptive to change the current behavior.

    1528: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventEnd()`, `PetscLogFlops()`
    1529: M*/

    1531: /*MC
    1532:   PetscLogEventEnd - Log the end of a user event.

    1534:   Synopsis:
    1535: #include <petsclog.h>
    1536:   PetscErrorCode PetscLogEventEnd(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)

    1538:   Not Collective

    1540:   Input Parameters:
    1541: + e  - `PetscLogEvent` obtained from `PetscLogEventRegister()`
    1542: . o1 - object associated with the event, or `NULL`
    1543: . o2 - object associated with the event, or `NULL`
    1544: . o3 - object associated with the event, or `NULL`
    1545: - o4 - object associated with the event, or `NULL`

    1547:   Fortran Synopsis:
    1548:   void PetscLogEventEnd(int e, PetscErrorCode ierr)

    1550:   Example Usage:
    1551: .vb
    1552:   PetscLogEvent USER_EVENT;

    1554:   PetscLogDouble user_event_flops;
    1555:   PetscLogEventRegister("User event", 0, &USER_EVENT);
    1556:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
    1557:   [code segment to monitor]
    1558:   PetscLogFlops(user_event_flops);
    1559:   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
    1560: .ve

    1562:   Level: intermediate

    1564: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogFlops()`
    1565: M*/

    1567: /*@C
    1568:   PetscLogStageGetPerfInfo - Return the performance information about the given stage

    1570:   No Fortran Support

    1572:   Input Parameters:
    1573: . stage - The stage number or `PETSC_DETERMINE` for the current stage

    1575:   Output Parameter:
    1576: . info - This structure is filled with the performance information

    1578:   Level: intermediate

    1580:   Notes:
    1581:   This is a low level routine used by the logging functions in PETSc.

    1583:   A `PETSCLOGHANDLERDEFAULT` must be running for this to work, having been started either with
    1584:   `PetscLogDefaultBegin()` or from the command line with `-log_view`.  If it was not started,
    1585:   all performance statistics in `info` will be zeroed.

    1587: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogGetDefaultHandler()`
    1588: @*/
    1589: PetscErrorCode PetscLogStageGetPerfInfo(PetscLogStage stage, PetscEventPerfInfo *info)
    1590: {
    1591:   PetscLogHandler     handler;
    1592:   PetscEventPerfInfo *event_info;

    1594:   PetscFunctionBegin;
    1595:   PetscAssertPointer(info, 2);
    1596:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
    1597:   if (handler) {
    1598:     PetscCall(PetscLogHandlerGetStagePerfInfo(handler, stage, &event_info));
    1599:     *info = *event_info;
    1600:   } else {
    1601:     PetscCall(PetscInfo(NULL, "Default log handler is not running, PetscLogStageGetPerfInfo() returning zeros\n"));
    1602:     PetscCall(PetscMemzero(info, sizeof(*info)));
    1603:   }
    1604:   PetscFunctionReturn(PETSC_SUCCESS);
    1605: }

    1607: /*@C
    1608:   PetscLogEventGetPerfInfo - Return the performance information about the given event in the given stage

    1610:   No Fortran Support

    1612:   Input Parameters:
    1613: + stage - The stage number or `PETSC_DETERMINE` for the current stage
    1614: - event - The event number

    1616:   Output Parameter:
    1617: . info - This structure is filled with the performance information

    1619:   Level: intermediate

    1621:   Note:
    1622:   This is a low level routine used by the logging functions in PETSc

    1624:   A `PETSCLOGHANDLERDEFAULT` must be running for this to work, having been started either with
    1625:   `PetscLogDefaultBegin()` or from the command line with `-log_view`.  If it was not started,
    1626:   all performance statistics in `info` will be zeroed.

    1628: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogGetDefaultHandler()`
    1629: @*/
    1630: PetscErrorCode PetscLogEventGetPerfInfo(PetscLogStage stage, PetscLogEvent event, PetscEventPerfInfo *info)
    1631: {
    1632:   PetscLogHandler     handler;
    1633:   PetscEventPerfInfo *event_info;

    1635:   PetscFunctionBegin;
    1636:   PetscAssertPointer(info, 3);
    1637:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
    1638:   if (handler) {
    1639:     PetscCall(PetscLogHandlerGetEventPerfInfo(handler, stage, event, &event_info));
    1640:     *info = *event_info;
    1641:   } else {
    1642:     PetscCall(PetscInfo(NULL, "Default log handler is not running, PetscLogEventGetPerfInfo() returning zeros\n"));
    1643:     PetscCall(PetscMemzero(info, sizeof(*info)));
    1644:   }
    1645:   PetscFunctionReturn(PETSC_SUCCESS);
    1646: }

    1648: /*@
    1649:   PetscLogEventSetDof - Set the nth number of degrees of freedom of a numerical problem associated with this event

    1651:   Not Collective

    1653:   Input Parameters:
    1654: + event - The event id to log
    1655: . n     - The dof index, in [0, 8)
    1656: - dof   - The number of dofs

    1658:   Options Database Key:
    1659: . -log_view - Activates log summary

    1661:   Level: developer

    1663:   Note:
    1664:   This is to enable logging of convergence

    1666: .seealso: `PetscLogEventSetError()`, `PetscLogEventRegister()`, `PetscLogGetDefaultHandler()`
    1667: @*/
    1668: PetscErrorCode PetscLogEventSetDof(PetscLogEvent event, PetscInt n, PetscLogDouble dof)
    1669: {
    1670:   PetscFunctionBegin;
    1671:   PetscCheck(!(n < 0) && !(n > 7), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Error index %" PetscInt_FMT " is not in [0, 8)", n);
    1672:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    1673:     PetscLogHandler h = PetscLogHandlers[i].handler;

    1675:     if (h) {
    1676:       PetscEventPerfInfo *event_info;

    1678:       PetscCall(PetscLogHandlerGetEventPerfInfo(h, PETSC_DEFAULT, event, &event_info));
    1679:       if (event_info) event_info->dof[n] = dof;
    1680:     }
    1681:   }
    1682:   PetscFunctionReturn(PETSC_SUCCESS);
    1683: }

    1685: /*@
    1686:   PetscLogEventSetError - Set the nth error associated with a numerical problem associated with this event

    1688:   Not Collective

    1690:   Input Parameters:
    1691: + event - The event id to log
    1692: . n     - The error index, in [0, 8)
    1693: - error - The error

    1695:   Options Database Key:
    1696: . -log_view - Activates log summary

    1698:   Level: developer

    1700:   Notes:
    1701:   This is to enable logging of convergence, and enable users to interpret the errors as they wish. For example,
    1702:   as different norms, or as errors for different fields

    1704:   This is a low level routine used by the logging functions in PETSc

    1706: .seealso: `PetscLogEventSetDof()`, `PetscLogEventRegister()`, `PetscLogGetDefaultHandler()`
    1707: @*/
    1708: PetscErrorCode PetscLogEventSetError(PetscLogEvent event, PetscInt n, PetscLogDouble error)
    1709: {
    1710:   PetscFunctionBegin;
    1711:   PetscCheck(!(n < 0) && !(n > 7), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Error index %" PetscInt_FMT " is not in [0, 8)", n);
    1712:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    1713:     PetscLogHandler h = PetscLogHandlers[i].handler;

    1715:     if (h) {
    1716:       PetscEventPerfInfo *event_info;

    1718:       PetscCall(PetscLogHandlerGetEventPerfInfo(h, PETSC_DEFAULT, event, &event_info));
    1719:       if (event_info) event_info->errors[n] = error;
    1720:     }
    1721:   }
    1722:   PetscFunctionReturn(PETSC_SUCCESS);
    1723: }

    1725: /*@
    1726:   PetscLogEventGetId - Returns the event id when given the event name.

    1728:   Not Collective

    1730:   Input Parameter:
    1731: . name - The event name

    1733:   Output Parameter:
    1734: . event - The event, or -1 if no event with that name exists

    1736:   Level: intermediate

    1738: .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
    1739: @*/
    1740: PetscErrorCode PetscLogEventGetId(const char name[], PetscLogEvent *event)
    1741: {
    1742:   PetscLogState state;

    1744:   PetscFunctionBegin;
    1745:   *event = -1;
    1746:   PetscCall(PetscLogGetState(&state));
    1747:   if (state) PetscCall(PetscLogStateGetEventFromName(state, name, event));
    1748:   PetscFunctionReturn(PETSC_SUCCESS);
    1749: }

    1751: /*@
    1752:   PetscLogEventGetName - Returns the event name when given the event id.

    1754:   Not Collective

    1756:   Input Parameter:
    1757: . event - The event

    1759:   Output Parameter:
    1760: . name - The event name

    1762:   Level: intermediate

    1764: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
    1765: @*/
    1766: PetscErrorCode PetscLogEventGetName(PetscLogEvent event, const char *name[])
    1767: {
    1768:   PetscLogEventInfo event_info;
    1769:   PetscLogState     state;

    1771:   PetscFunctionBegin;
    1772:   *name = NULL;
    1773:   PetscCall(PetscLogGetState(&state));
    1774:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
    1775:   PetscCall(PetscLogStateEventGetInfo(state, event, &event_info));
    1776:   *name = event_info.name;
    1777:   PetscFunctionReturn(PETSC_SUCCESS);
    1778: }

    1780: /*@
    1781:   PetscLogEventsPause - Put event logging into "paused" mode: timers and counters for in-progress events are paused, and any events that happen before logging is resumed with `PetscLogEventsResume()` are logged in the "Main Stage" of execution.

    1783:   Not collective

    1785:   Level: advanced

    1787:   Notes:
    1788:   When an external library or runtime has is initialized it can involve lots of setup time that skews the statistics of any unrelated running events: this function is intended to isolate such calls in the default log summary (`PetscLogDefaultBegin()`, `PetscLogView()`).

    1790:   Other log handlers (such as the nested handler, `PetscLogNestedBegin()`) will ignore this function.

    1792: .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsResume()`, `PetscLogGetDefaultHandler()`
    1793: @*/
    1794: PetscErrorCode PetscLogEventsPause(void)
    1795: {
    1796:   PetscFunctionBegin;
    1797:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    1798:     PetscLogHandler h = PetscLogHandlers[i].handler;

    1800:     if (h) PetscCall(PetscLogHandlerEventsPause(h));
    1801:   }
    1802:   PetscFunctionReturn(PETSC_SUCCESS);
    1803: }

    1805: /*@
    1806:   PetscLogEventsResume - Return logging to normal behavior after it was paused with `PetscLogEventsPause()`.

    1808:   Not collective

    1810:   Level: advanced

    1812: .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsPause()`, `PetscLogGetDefaultHandler()`
    1813: @*/
    1814: PetscErrorCode PetscLogEventsResume(void)
    1815: {
    1816:   PetscFunctionBegin;
    1817:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    1818:     PetscLogHandler h = PetscLogHandlers[i].handler;

    1820:     if (h) PetscCall(PetscLogHandlerEventsResume(h));
    1821:   }
    1822:   PetscFunctionReturn(PETSC_SUCCESS);
    1823: }

    1825: /*------------------------------------------------ Class Functions --------------------------------------------------*/

    1827: /*MC
    1828:    PetscLogObjectCreate - Log the creation of a `PetscObject`

    1830:    Synopsis:
    1831: #include <petsclog.h>
    1832:    PetscErrorCode PetscLogObjectCreate(PetscObject h)

    1834:    Not Collective

    1836:    Input Parameters:
    1837: .  h - A `PetscObject`

    1839:    Level: developer

    1841:    Developer Note:
    1842:      Called internally by PETSc when creating objects: users do not need to call this directly.
    1843:      Notification of the object creation is sent to each `PetscLogHandler` that is running.

    1845: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectDestroy()`
    1846: M*/

    1848: /*MC
    1849:    PetscLogObjectDestroy - Logs the destruction of a `PetscObject`

    1851:    Synopsis:
    1852: #include <petsclog.h>
    1853:    PetscErrorCode PetscLogObjectDestroy(PetscObject h)

    1855:    Not Collective

    1857:    Input Parameters:
    1858: .  h - A `PetscObject`

    1860:    Level: developer

    1862:    Developer Note:
    1863:      Called internally by PETSc when destroying objects: users do not need to call this directly.
    1864:      Notification of the object creation is sent to each `PetscLogHandler` that is running.

    1866: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectCreate()`
    1867: M*/

    1869: /*@
    1870:   PetscLogClassGetClassId - Returns the `PetscClassId` when given the class name.

    1872:   Not Collective

    1874:   Input Parameter:
    1875: . name - The class name

    1877:   Output Parameter:
    1878: . classid - The `PetscClassId` id, or -1 if no class with that name exists

    1880:   Level: intermediate

    1882: .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
    1883: @*/
    1884: PetscErrorCode PetscLogClassGetClassId(const char name[], PetscClassId *classid)
    1885: {
    1886:   PetscLogClass     log_class;
    1887:   PetscLogClassInfo class_info;
    1888:   PetscLogState     state;

    1890:   PetscFunctionBegin;
    1891:   *classid = -1;
    1892:   PetscCall(PetscLogGetState(&state));
    1893:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
    1894:   PetscCall(PetscLogStateGetClassFromName(state, name, &log_class));
    1895:   if (log_class < 0) {
    1896:     *classid = -1;
    1897:     PetscFunctionReturn(PETSC_SUCCESS);
    1898:   }
    1899:   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
    1900:   *classid = class_info.classid;
    1901:   PetscFunctionReturn(PETSC_SUCCESS);
    1902: }

    1904: /*@C
    1905:   PetscLogClassIdGetName - Returns a `PetscClassId`'s name.

    1907:   Not Collective

    1909:   Input Parameter:
    1910: . classid - A `PetscClassId`

    1912:   Output Parameter:
    1913: . name - The class name

    1915:   Level: intermediate

    1917: .seealso: [](ch_profiling), `PetscLogClassRegister()`, `PetscLogClassBegin()`, `PetscLogClassEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadClass()`
    1918: @*/
    1919: PetscErrorCode PetscLogClassIdGetName(PetscClassId classid, const char **name)
    1920: {
    1921:   PetscLogClass     log_class;
    1922:   PetscLogClassInfo class_info;
    1923:   PetscLogState     state;

    1925:   PetscFunctionBegin;
    1926:   PetscCall(PetscLogGetState(&state));
    1927:   PetscCall(PetscLogStateGetClassFromClassId(state, classid, &log_class));
    1928:   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
    1929:   *name = class_info.name;
    1930:   PetscFunctionReturn(PETSC_SUCCESS);
    1931: }

    1933: /*------------------------------------------------ Output Functions -------------------------------------------------*/
    1934: /*@
    1935:   PetscLogDump - Dumps logs of objects to a file. This file is intended to
    1936:   be read by bin/petscview. This program no longer exists.

    1938:   Collective on `PETSC_COMM_WORLD`

    1940:   Input Parameter:
    1941: . sname - an optional file name

    1943:   Example Usage:
    1944: .vb
    1945:   PetscInitialize(...);
    1946:   PetscLogDefaultBegin();
    1947:   // ... code ...
    1948:   PetscLogDump(filename);
    1949:   PetscFinalize();
    1950: .ve

    1952:   Level: advanced

    1954:   Note:
    1955:   The default file name is Log.<rank> where <rank> is the MPI process rank. If no name is specified,
    1956:   this file will be used.

    1958: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
    1959: @*/
    1960: PetscErrorCode PetscLogDump(const char sname[])
    1961: {
    1962:   PetscLogHandler handler;

    1964:   PetscFunctionBegin;
    1965:   PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
    1966:   PetscCall(PetscLogHandlerDump(handler, sname));
    1967:   PetscFunctionReturn(PETSC_SUCCESS);
    1968: }

    1970: /*@
    1971:   PetscLogMPEDump - Dumps the MPE logging info to file for later use with Jumpshot.

    1973:   Collective on `PETSC_COMM_WORLD`

    1975:   Input Parameter:
    1976: . sname - filename for the MPE logfile

    1978:   Level: advanced

    1980: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogMPEBegin()`
    1981: @*/
    1982: PetscErrorCode PetscLogMPEDump(const char sname[])
    1983: {
    1984:   PetscFunctionBegin;
    1985:   #if defined(PETSC_HAVE_MPE)
    1986:   if (PetscBeganMPE) {
    1987:     char name[PETSC_MAX_PATH_LEN];

    1989:     PetscCall(PetscInfo(0, "Finalizing MPE.\n"));
    1990:     if (sname) {
    1991:       PetscCall(PetscStrncpy(name, sname, sizeof(name)));
    1992:     } else {
    1993:       PetscCall(PetscGetProgramName(name, sizeof(name)));
    1994:     }
    1995:     PetscCall(MPE_Finish_log(name));
    1996:   } else {
    1997:     PetscCall(PetscInfo(0, "Not finalizing MPE (not started by PETSc).\n"));
    1998:   }
    1999:   #else
    2000:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
    2001:   #endif
    2002:   PetscFunctionReturn(PETSC_SUCCESS);
    2003: }

    2005: /*@
    2006:   PetscLogView - Prints a summary of the logging.

    2008:   Collective

    2010:   Input Parameter:
    2011: . viewer - an ASCII viewer

    2013:   Options Database Keys:
    2014: + -log_view [:filename]                    - Prints summary of log information
    2015: . -log_view :filename.py:ascii_info_detail - Saves logging information from each process as a Python file
    2016: . -log_view :filename.xml:ascii_xml        - Saves a summary of the logging information in a nested format (see below for how to view it)
    2017: . -log_view :filename.txt:ascii_flamegraph - Saves logging information in a format suitable for visualising as a Flame Graph (see below for how to view it)
    2018: . -log_view_memory                         - Also display memory usage in each event
    2019: . -log_view_gpu_time                       - Also display time in each event for GPU kernels (Note this may slow the computation)
    2020: . -log_view_gpu_energy                     - Also display energy (estimated with power*gtime) in Joules for GPU kernels
    2021: . -log_view_gpu_energy_meter               - [Experimental] Also display energy (readings from energy meters) in Joules for GPU kernels. This option is ignored if -log_view_gpu_energy is provided.
    2022: . -log_all                                 - Saves a file Log.rank for each MPI rank with details of each step of the computation
    2023: - -log_trace [filename]                    - Displays a trace of what each process is doing

    2025:   Level: beginner

    2027:   Notes:
    2028:   It is possible to control the logging programmatically but we recommend using the options database approach whenever possible
    2029:   By default the summary is printed to stdout.

    2031:   Before calling this routine you must have called either PetscLogDefaultBegin() or PetscLogNestedBegin()

    2033:   If PETSc is configured with --with-log=0 then this functionality is not available

    2035:   To view the nested XML format filename.xml first copy  ${PETSC_DIR}/share/petsc/xml/performance_xml2html.xsl to the current
    2036:   directory then open filename.xml with your browser. Specific notes for certain browsers
    2037: .vb
    2038:     Firefox and Internet explorer - simply open the file
    2039:     Google Chrome - you must start up Chrome with the option --allow-file-access-from-files
    2040:     Safari - see https://ccm.net/faq/36342-safari-how-to-enable-local-file-access
    2041: .ve
    2042:   or one can use the package <http://xmlsoft.org/XSLT/xsltproc2.html> to translate the xml file to html and then open it with
    2043:   your browser.
    2044:   Alternatively, use the script ${PETSC_DIR}/lib/petsc/bin/petsc-performance-view to automatically open a new browser
    2045:   window and render the XML log file contents.

    2047:   The nested XML format was kindly donated by Koos Huijssen and Christiaan M. Klaij  MARITIME  RESEARCH  INSTITUTE  NETHERLANDS

    2049:   The Flame Graph output can be visualised using either the original Flame Graph script <https://github.com/brendangregg/FlameGraph>
    2050:   or using speedscope <https://www.speedscope.app>.
    2051:   Old XML profiles may be converted into this format using the script ${PETSC_DIR}/lib/petsc/bin/xml2flamegraph.py.

    2053: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogDump()`
    2054: @*/
    2055: PetscErrorCode PetscLogView(PetscViewer viewer)
    2056: {
    2057:   PetscBool         isascii;
    2058:   PetscViewerFormat format;
    2059:   int               stage;
    2060:   PetscLogState     state;
    2061:   PetscIntStack     temp_stack;
    2062:   PetscLogHandler   handler;
    2063:   PetscBool         is_empty;

    2065:   PetscFunctionBegin;
    2066:   PetscCall(PetscLogGetState(&state));
    2067:   /* Pop off any stages the user forgot to remove */
    2068:   PetscCall(PetscIntStackCreate(&temp_stack));
    2069:   PetscCall(PetscLogStateGetCurrentStage(state, &stage));
    2070:   while (stage >= 0) {
    2071:     PetscCall(PetscLogStagePop());
    2072:     PetscCall(PetscIntStackPush(temp_stack, stage));
    2073:     PetscCall(PetscLogStateGetCurrentStage(state, &stage));
    2074:   }
    2075:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
    2076:   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Currently can only view logging to ASCII");
    2077:   PetscCall(PetscViewerGetFormat(viewer, &format));
    2078:   if (format == PETSC_VIEWER_ASCII_XML || format == PETSC_VIEWER_ASCII_FLAMEGRAPH) {
    2079:     PetscCall(PetscLogGetHandler(PETSCLOGHANDLERNESTED, &handler));
    2080:     PetscCall(PetscLogHandlerView(handler, viewer));
    2081:   } else {
    2082:     PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
    2083:     PetscCall(PetscLogHandlerView(handler, viewer));
    2084:   }
    2085:   PetscCall(PetscIntStackEmpty(temp_stack, &is_empty));
    2086:   while (!is_empty) {
    2087:     PetscCall(PetscIntStackPop(temp_stack, &stage));
    2088:     PetscCall(PetscLogStagePush(stage));
    2089:     PetscCall(PetscIntStackEmpty(temp_stack, &is_empty));
    2090:   }
    2091:   PetscCall(PetscIntStackDestroy(temp_stack));
    2092:   PetscFunctionReturn(PETSC_SUCCESS);
    2093: }

    2095: /*@C
    2096:   PetscLogViewFromOptions - Processes command line options to determine if/how a `PetscLog` is to be viewed.

    2098:   Collective on `PETSC_COMM_WORLD`

    2100:   Level: developer

    2102:   Note:
    2103:   This function has a different API and behavior than `PetscObjectViewFromOptions()`

    2105: .seealso: [](ch_profiling), `PetscLogView()`
    2106: @*/
    2107: PetscErrorCode PetscLogViewFromOptions(void)
    2108: {
    2109:   PetscInt          n_max = PETSC_LOG_VIEW_FROM_OPTIONS_MAX;
    2110:   PetscViewer       viewers[PETSC_LOG_VIEW_FROM_OPTIONS_MAX];
    2111:   PetscViewerFormat formats[PETSC_LOG_VIEW_FROM_OPTIONS_MAX];
    2112:   PetscBool         flg;

    2114:   PetscFunctionBegin;
    2115:   PetscCall(PetscOptionsCreateViewers(PETSC_COMM_WORLD, NULL, NULL, "-log_view", &n_max, viewers, formats, &flg));
    2116:   /*
    2117:      PetscLogHandlerView_Default_Info() wants to be sure that the only objects still around are these viewers, so keep track of how many there are
    2118:    */
    2119:   PetscLogNumViewersCreated = n_max;
    2120:   for (PetscInt i = 0; i < n_max; i++) {
    2121:     PetscInt refct;

    2123:     PetscCall(PetscViewerPushFormat(viewers[i], formats[i]));
    2124:     PetscCall(PetscLogView(viewers[i]));
    2125:     PetscCall(PetscViewerPopFormat(viewers[i]));
    2126:     PetscCall(PetscObjectGetReference((PetscObject)viewers[i], &refct));
    2127:     PetscCall(PetscViewerDestroy(&viewers[i]));
    2128:     if (refct == 1) PetscLogNumViewersDestroyed++;
    2129:   }
    2130:   PetscLogNumViewersDestroyed = 0;
    2131:   PetscFunctionReturn(PETSC_SUCCESS);
    2132: }

    2134: PETSC_INTERN PetscErrorCode PetscLogHandlerNestedSetThreshold(PetscLogHandler, PetscLogDouble, PetscLogDouble *);

    2136: /*@
    2137:   PetscLogSetThreshold - Set the threshold time for logging the events; this is a percentage out of 100, so 1. means any event
    2138:   that takes 1 or more percent of the time.

    2140:   Logically Collective on `PETSC_COMM_WORLD`

    2142:   Input Parameter:
    2143: . newThresh - the threshold to use

    2145:   Output Parameter:
    2146: . oldThresh - the previously set threshold value

    2148:   Options Database Keys:
    2149: . -log_view :filename.xml:ascii_xml - Prints an XML summary of flop and timing information to the file

    2151:   Example Usage:
    2152: .vb
    2153:   PetscInitialize(...);
    2154:   PetscLogNestedBegin();
    2155:   PetscLogSetThreshold(0.1,&oldthresh);
    2156:   // ... code ...
    2157:   PetscLogView(viewer);
    2158:   PetscFinalize();
    2159: .ve

    2161:   Level: advanced

    2163:   Note:
    2164:   This threshold is only used by the nested log handler

    2166: .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`,
    2167:           `PetscLogNestedBegin()`
    2168: @*/
    2169: PetscErrorCode PetscLogSetThreshold(PetscLogDouble newThresh, PetscLogDouble *oldThresh)
    2170: {
    2171:   PetscLogHandler handler;

    2173:   PetscFunctionBegin;
    2174:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERNESTED, &handler));
    2175:   PetscCall(PetscLogHandlerNestedSetThreshold(handler, newThresh, oldThresh));
    2176:   PetscFunctionReturn(PETSC_SUCCESS);
    2177: }

    2179: /*----------------------------------------------- Counter Functions -------------------------------------------------*/
    2180: /*@
    2181:   PetscGetFlops - Returns the number of flops used on this processor
    2182:   since the program began.

    2184:   Not Collective

    2186:   Output Parameter:
    2187: . flops - number of floating point operations

    2189:   Level: intermediate

    2191:   Notes:
    2192:   A global counter logs all PETSc flop counts.  The user can use
    2193:   `PetscLogFlops()` to increment this counter to include flops for the
    2194:   application code.

    2196:   A separate counter `PetscLogGpuFlops()` logs the flops that occur on any GPU associated with this MPI rank

    2198: .seealso: [](ch_profiling), `PetscLogGpuFlops()`, `PetscTime()`, `PetscLogFlops()`
    2199: @*/
    2200: PetscErrorCode PetscGetFlops(PetscLogDouble *flops)
    2201: {
    2202:   PetscFunctionBegin;
    2203:   *flops = petsc_TotalFlops;
    2204:   PetscFunctionReturn(PETSC_SUCCESS);
    2205: }

    2207: /*@C
    2208:   PetscLogObjectState - Record information about an object with the default log handler

    2210:   Not Collective

    2212:   Input Parameters:
    2213: + obj    - the `PetscObject`
    2214: . format - a printf-style format string
    2215: - ...    - printf arguments to format

    2217:   Level: developer

    2219: .seealso: [](ch_profiling), `PetscLogObjectCreate()`, `PetscLogObjectDestroy()`, `PetscLogGetDefaultHandler()`
    2220: @*/
    2221: PetscErrorCode PetscLogObjectState(PetscObject obj, const char format[], ...)
    2222: {
    2223:   PetscFunctionBegin;
    2224:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    2225:     PetscLogHandler h = PetscLogHandlers[i].handler;

    2227:     if (h) {
    2228:       va_list Argp;
    2229:       va_start(Argp, format);
    2230:       PetscCall(PetscLogHandlerLogObjectState_Internal(h, obj, format, Argp));
    2231:       va_end(Argp);
    2232:     }
    2233:   }
    2234:   PetscFunctionReturn(PETSC_SUCCESS);
    2235: }

    2237: /*MC
    2238:   PetscLogFlops - Adds floating point operations to the global counter.

    2240:   Synopsis:
    2241: #include <petsclog.h>
    2242:   PetscErrorCode PetscLogFlops(PetscLogDouble f)

    2244:   Not Collective

    2246:   Input Parameter:
    2247: . f - flop counter

    2249:   Example Usage:
    2250: .vb
    2251:   PetscLogEvent USER_EVENT;

    2253:   PetscLogEventRegister("User event", 0, &USER_EVENT);
    2254:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
    2255:   [code segment to monitor]
    2256:   PetscLogFlops(user_flops)
    2257:   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
    2258: .ve

    2260:   Level: intermediate

    2262:   Note:
    2263:    A global counter logs all PETSc flop counts. The user can use PetscLogFlops() to increment
    2264:    this counter to include flops for the application code.

    2266: .seealso: [](ch_profiling), `PetscLogGpuFlops()`, `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscGetFlops()`
    2267: M*/

    2269: /*MC
    2270:   PetscPreLoadBegin - Begin a segment of code that may be preloaded (run twice) to get accurate
    2271:   timings

    2273:   Synopsis:
    2274: #include <petsclog.h>
    2275:   void PetscPreLoadBegin(PetscBool flag, char *name);

    2277:   Not Collective

    2279:   Input Parameters:
    2280: + flag - `PETSC_TRUE` to run twice, `PETSC_FALSE` to run once, may be overridden with command
    2281:          line option `-preload true|false`
    2282: - name - name of first stage (lines of code timed separately with `-log_view`) to be preloaded

    2284:   Example Usage:
    2285: .vb
    2286:   PetscPreLoadBegin(PETSC_TRUE, "first stage");
    2287:   // lines of code
    2288:   PetscPreLoadStage("second stage");
    2289:   // lines of code
    2290:   PetscPreLoadEnd();
    2291: .ve

    2293:   Level: intermediate

    2295:   Note:
    2296:   Only works in C/C++, not Fortran

    2298:   Flags available within the macro\:
    2299: + PetscPreLoadingUsed - `PETSC_TRUE` if we are or have done preloading
    2300: . PetscPreLoadingOn   - `PETSC_TRUE` if it is CURRENTLY doing preload
    2301: . PetscPreLoadIt      - `0` for the first computation (with preloading turned off it is only
    2302:                         `0`) `1`  for the second
    2303: - PetscPreLoadMax     - number of times it will do the computation, only one when preloading is
    2304:                         turned on

    2306:   The first two variables are available throughout the program, the second two only between the
    2307:   `PetscPreLoadBegin()` and `PetscPreLoadEnd()`

    2309: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
    2310: M*/

    2312: /*MC
    2313:   PetscPreLoadEnd - End a segment of code that may be preloaded (run twice) to get accurate
    2314:   timings

    2316:   Synopsis:
    2317: #include <petsclog.h>
    2318:   void PetscPreLoadEnd(void);

    2320:   Not Collective

    2322:   Example Usage:
    2323: .vb
    2324:   PetscPreLoadBegin(PETSC_TRUE, "first stage");
    2325:   // lines of code
    2326:   PetscPreLoadStage("second stage");
    2327:   // lines of code
    2328:   PetscPreLoadEnd();
    2329: .ve

    2331:   Level: intermediate

    2333:   Note:
    2334:   Only works in C/C++ not Fortran

    2336: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadStage()`
    2337: M*/

    2339: /*MC
    2340:   PetscPreLoadStage - Start a new segment of code to be timed separately to get accurate timings

    2342:   Synopsis:
    2343: #include <petsclog.h>
    2344:   void PetscPreLoadStage(char *name);

    2346:   Not Collective

    2348:   Example Usage:
    2349: .vb
    2350:   PetscPreLoadBegin(PETSC_TRUE,"first stage");
    2351:   // lines of code
    2352:   PetscPreLoadStage("second stage");
    2353:   // lines of code
    2354:   PetscPreLoadEnd();
    2355: .ve

    2357:   Level: intermediate

    2359:   Note:
    2360:   Only works in C/C++ not Fortran

    2362: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`
    2363: M*/

    2365:   #if PetscDefined(HAVE_DEVICE)
    2366: #include <petsc/private/deviceimpl.h>

    2368: /*@
    2369:   PetscLogGpuTime - turn on the logging of GPU time for GPU kernels

    2371:   Options Database Key:
    2372: . -log_view_gpu_time - provide the GPU times for all events in the `-log_view` output

    2374:   Level: advanced

    2376:   Notes:
    2377:   Turning on the timing of the GPU kernels can slow down the entire computation and should only
    2378:   be used when studying the performance of individual operations on GPU such as vector operations and
    2379:   matrix-vector operations.

    2381:   If this option is not used then times for most of the events in the `-log_view` output will be listed as NaN, indicating the times are not available

    2383:   This routine should only be called once near the beginning of the program. Once it is started
    2384:   it cannot be turned off.

    2386: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTimeBegin()`
    2387: @*/
    2388: PetscErrorCode PetscLogGpuTime(void)
    2389: {
    2390:   PetscFunctionBegin;
    2391:   PetscCheck(petsc_gtime == 0.0, PETSC_COMM_SELF, PETSC_ERR_SUP, "GPU logging has already been turned on");
    2392:   PetscLogGpuTimeFlag = PETSC_TRUE;
    2393:   PetscFunctionReturn(PETSC_SUCCESS);
    2394: }

    2396: /*@
    2397:   PetscLogGpuTimeBegin - Start timer for device

    2399:   Level: intermediate

    2401:   Notes:
    2402:   When GPU is enabled, the timer is run on the GPU, it is a separate logging of time
    2403:   devoted to GPU computations (excluding kernel launch times).

    2405:   When GPU is not available, the timer is run on the CPU, it is a separate logging of
    2406:   time devoted to GPU computations (including kernel launch times).

    2408:   There is no need to call WaitForCUDA() or WaitForHIP() between `PetscLogGpuTimeBegin()` and
    2409:   `PetscLogGpuTimeEnd()`

    2411:   This timer should NOT include times for data transfers between the GPU and CPU, nor setup
    2412:   actions such as allocating space.

    2414:   The regular logging captures the time for data transfers and any CPU activities during the
    2415:   event. It is used to compute the flop rate on the GPU as it is actively engaged in running a
    2416:   kernel.

    2418:   Developer Notes:
    2419:   The GPU event timer captures the execution time of all the kernels launched in the default
    2420:   stream by the CPU between `PetscLogGpuTimeBegin()` and `PetscLogGpuTimeEnd()`.

    2422:   `PetscLogGpuTimeBegin()` and `PetscLogGpuTimeEnd()` insert the begin and end events into the
    2423:   default stream (stream 0). The device will record a time stamp for the event when it reaches
    2424:   that event in the stream. The function xxxEventSynchronize() is called in
    2425:   `PetscLogGpuTimeEnd()` to block CPU execution, but not continued GPU execution, until the
    2426:   timer event is recorded.

    2428: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTime()`
    2429: @*/
    2430: PetscErrorCode PetscLogGpuTimeBegin(void)
    2431: {
    2432:   PetscBool isActive;

    2434:   PetscFunctionBegin;
    2435:   PetscCall(PetscLogEventBeginIsActive(&isActive));
    2436:   if (!isActive || !PetscLogGpuTimeFlag) PetscFunctionReturn(PETSC_SUCCESS);
    2437:   if (!PetscDefined(HAVE_KOKKOS_WITHOUT_GPU)) {
    2438:     PetscDeviceContext dctx;

    2440:     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
    2441:     PetscCall(PetscDeviceContextBeginTimer_Internal(dctx));
    2442:   } else {
    2443:     PetscCall(PetscTimeSubtract(&petsc_gtime));
    2444:   }
    2445:   PetscFunctionReturn(PETSC_SUCCESS);
    2446: }

    2448: /*@
    2449:   PetscLogGpuTimeEnd - Stop timer for device

    2451:   Level: intermediate

    2453: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeBegin()`
    2454: @*/
    2455: PetscErrorCode PetscLogGpuTimeEnd(void)
    2456: {
    2457:   PetscBool isActive;

    2459:   PetscFunctionBegin;
    2460:   PetscCall(PetscLogEventEndIsActive(&isActive));
    2461:   if (!isActive || !PetscLogGpuTimeFlag) PetscFunctionReturn(PETSC_SUCCESS);
    2462:   if (!PetscDefined(HAVE_KOKKOS_WITHOUT_GPU)) {
    2463:     PetscDeviceContext dctx;
    2464:     PetscLogDouble     elapsed;

    2466:     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
    2467:     PetscCall(PetscDeviceContextEndTimer_Internal(dctx, &elapsed));
    2468:     petsc_gtime += (elapsed / 1000.0);
    2469:     #if PetscDefined(HAVE_CUDA_VERSION_12_2PLUS)
    2470:     if (PetscLogGpuEnergyFlag) {
    2471:       PetscLogDouble power;
    2472:       PetscCall(PetscDeviceContextGetPower_Internal(dctx, &power));
    2473:       petsc_genergy += (power * elapsed / 1000000.0); // convert to Joules
    2474:     }
    2475:     #endif
    2476:   } else {
    2477:     PetscCall(PetscTimeAdd(&petsc_gtime));
    2478:   }
    2479:   PetscFunctionReturn(PETSC_SUCCESS);
    2480: }

    2482: /*@
    2483:   PetscLogGpuEnergy - turn on the logging of GPU energy (estimated with power*gtime) for GPU kernels

    2485:   Options Database Key:
    2486: . -log_view_gpu_energy - provide the GPU energy consumption (estimated with power*gtime) for all events in the `-log_view` output

    2488:   Level: advanced

    2490:   Note:
    2491:   This option is mutually exclusive to `-log_view_gpu_energy_meter`.

    2493:   Developer Note:
    2494:   This option turns on energy monitoring of GPU kernels and requires CUDA version >= 12.2. The energy consumption is estimated as
    2495:   instant_power * gpu_kernel_time. Due to the delay in NVML power sampling, we read the instantaneous power draw at the end of each
    2496:   event using `nvmlDeviceGetFieldValues()` with the field ID `NVML_FI_DEV_POWER_INSTANT`.

    2498: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuEnergyMeter()`
    2499: @*/
    2500: PetscErrorCode PetscLogGpuEnergy(void)
    2501: {
    2502:   PetscFunctionBegin;
    2503:   PetscCheck(PetscDefined(HAVE_CUDA_VERSION_12_2PLUS), PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "-log_view_gpu_energy requires CUDA version >= 12.2");
    2504:   PetscCheck(petsc_genergy == 0.0, PETSC_COMM_SELF, PETSC_ERR_SUP, "GPU energy logging has already been turned on");
    2505:   PetscLogGpuEnergyFlag      = PETSC_TRUE;
    2506:   PetscLogGpuEnergyMeterFlag = PETSC_FALSE;
    2507:   PetscFunctionReturn(PETSC_SUCCESS);
    2508: }

    2510: /*@
    2511:   PetscLogGpuEnergyMeter - turn on the logging of GPU energy (readings from energy meters) for GPU kernels

    2513:   Options Database Key:
    2514: . -log_view_gpu_energy_meter - provide the GPU energy (readings from energy meters) consumption for all events in the `-log_view` output

    2516:   Level: advanced

    2518:   Note:
    2519:   This option is mutually exclusive to `-log_view_gpu_energy`.

    2521:   Developer Note:
    2522:   This option turns on energy monitoring of GPU kernels. The energy consumption is measured directly using the NVML API
    2523:   `nvmlDeviceGetTotalEnergyConsumption()`, which returns the total energy used by the GPU since the driver was last initialized.
    2524:   For newer GPUs, energy readings are updated every 20-100ms, so this approach may be inaccurate for short-duration GPU events.

    2526: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuEnergyMeterEnd()`, `PetscLogGpuEnergyMeterBegin()`
    2527: @*/
    2528: PetscErrorCode PetscLogGpuEnergyMeter(void)
    2529: {
    2530:   PetscFunctionBegin;
    2531:   PetscCheck(petsc_genergy == 0.0, PETSC_COMM_SELF, PETSC_ERR_SUP, "GPU energy logging has already been turned on");
    2532:   PetscLogGpuEnergyMeterFlag = PETSC_TRUE;
    2533:   PetscLogGpuEnergyFlag      = PETSC_FALSE;
    2534:   PetscFunctionReturn(PETSC_SUCCESS);
    2535: }

    2537: /*@
    2538:   PetscLogGpuEnergyMeterBegin - Start energy meter for device

    2540:   Level: intermediate

    2542:   Notes:
    2543:   The GPU event energy meter captures the energy used by the GPU between `PetscLogGpuEnergyMeterBegin()` and `PetscLogGpuEnergyMeterEnd()`.

    2545:   `PetscLogGpuEnergyMeterBegin()` and `PetscLogGpuEnergyMeterEnd()` collect the energy readings using `nvmlDeviceGetTotalEnergyConsumption()`.
    2546:   The function `cupmStreamSynchronize()` is called before the energy query to ensure completion.

    2548: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuEnergyMeterEnd()`, `PetscLogGpuEnergyMeter()`
    2549: @*/
    2550: PetscErrorCode PetscLogGpuEnergyMeterBegin(void)
    2551: {
    2552:   PetscBool isActive;

    2554:   PetscFunctionBegin;
    2555:   PetscCall(PetscLogEventBeginIsActive(&isActive));
    2556:   if (!isActive || !PetscLogGpuEnergyMeterFlag) PetscFunctionReturn(PETSC_SUCCESS);
    2557:   if (!PetscDefined(HAVE_KOKKOS_WITHOUT_GPU)) {
    2558:     PetscDeviceContext dctx;

    2560:     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
    2561:     PetscCall(PetscDeviceContextBeginEnergyMeter_Internal(dctx));
    2562:   }
    2563:   PetscFunctionReturn(PETSC_SUCCESS);
    2564: }

    2566: /*@
    2567:   PetscLogGpuEnergyMeterEnd - Stop energy meter for device

    2569:   Level: intermediate

    2571: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuEnergyMeterBegin()`
    2572: @*/
    2573: PetscErrorCode PetscLogGpuEnergyMeterEnd(void)
    2574: {
    2575:   PetscBool isActive;

    2577:   PetscFunctionBegin;
    2578:   PetscCall(PetscLogEventEndIsActive(&isActive));
    2579:   if (!isActive || !PetscLogGpuEnergyMeterFlag) PetscFunctionReturn(PETSC_SUCCESS);
    2580:   if (!PetscDefined(HAVE_KOKKOS_WITHOUT_GPU)) {
    2581:     PetscDeviceContext dctx;
    2582:     PetscLogDouble     energy;

    2584:     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
    2585:     PetscCall(PetscDeviceContextEndEnergyMeter_Internal(dctx, &energy));
    2586:     petsc_genergy_meter += (energy / 1000.0); // convert to Joules
    2587:   }
    2588:   PetscFunctionReturn(PETSC_SUCCESS);
    2589: }
    2590:   #endif /* end of PETSC_HAVE_DEVICE */

    2592: #endif /* PETSC_USE_LOG*/

    2594: PetscClassId PETSC_LARGEST_CLASSID = PETSC_SMALLEST_CLASSID;
    2595: PetscClassId PETSC_OBJECT_CLASSID  = 0;

    2597: static PetscBool PetscLogInitializeCalled = PETSC_FALSE;

    2599: PETSC_INTERN PetscErrorCode PetscLogInitialize(void)
    2600: {
    2601:   int stage;

    2603:   PetscFunctionBegin;
    2604:   if (PetscLogInitializeCalled) PetscFunctionReturn(PETSC_SUCCESS);
    2605:   PetscLogInitializeCalled = PETSC_TRUE;
    2606:   if (PetscDefined(USE_LOG)) {
    2607:     /* Setup default logging structures */
    2608:     PetscCall(PetscLogStateCreate(&petsc_log_state));
    2609:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
    2610:       if (PetscLogHandlers[i].handler) PetscCall(PetscLogHandlerSetState(PetscLogHandlers[i].handler, petsc_log_state));
    2611:     }
    2612:     PetscCall(PetscLogStateStageRegister(petsc_log_state, "Main Stage", &stage));
    2613:     PetscCall(PetscSpinlockCreate(&PetscLogSpinLock));
    2614: #if defined(PETSC_HAVE_THREADSAFETY)
    2615:     petsc_log_tid = 0;
    2616:     petsc_log_gid = 0;
    2617: #endif

    2619:     /* All processors sync here for more consistent logging */
    2620:     PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
    2621:     PetscCall(PetscTime(&petsc_BaseTime));
    2622:     PetscCall(PetscLogStagePush(stage));
    2623:   }
    2624:   PetscFunctionReturn(PETSC_SUCCESS);
    2625: }

    2627: PETSC_INTERN PetscErrorCode PetscLogFinalize(void)
    2628: {
    2629:   PetscFunctionBegin;
    2630:   if (PetscDefined(USE_LOG)) {
    2631:     /* Resetting phase */
    2632:     // pop remaining stages
    2633:     if (petsc_log_state) {
    2634:       while (petsc_log_state->current_stage >= 0) PetscCall(PetscLogStagePop());
    2635:     }
    2636:     for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) PetscCall(PetscLogHandlerDestroy(&PetscLogHandlers[i].handler));
    2637:     PetscCall(PetscArrayzero(PetscLogHandlers, PETSC_LOG_HANDLER_MAX));
    2638:     PetscCall(PetscLogStateDestroy(&petsc_log_state));

    2640:     petsc_TotalFlops         = 0.0;
    2641:     petsc_BaseTime           = 0.0;
    2642:     petsc_TotalFlops         = 0.0;
    2643:     petsc_send_ct            = 0.0;
    2644:     petsc_recv_ct            = 0.0;
    2645:     petsc_send_len           = 0.0;
    2646:     petsc_recv_len           = 0.0;
    2647:     petsc_isend_ct           = 0.0;
    2648:     petsc_irecv_ct           = 0.0;
    2649:     petsc_isend_len          = 0.0;
    2650:     petsc_irecv_len          = 0.0;
    2651:     petsc_wait_ct            = 0.0;
    2652:     petsc_wait_any_ct        = 0.0;
    2653:     petsc_wait_all_ct        = 0.0;
    2654:     petsc_sum_of_waits_ct    = 0.0;
    2655:     petsc_allreduce_ct       = 0.0;
    2656:     petsc_gather_ct          = 0.0;
    2657:     petsc_scatter_ct         = 0.0;
    2658:     petsc_TotalFlops_th      = 0.0;
    2659:     petsc_send_ct_th         = 0.0;
    2660:     petsc_recv_ct_th         = 0.0;
    2661:     petsc_send_len_th        = 0.0;
    2662:     petsc_recv_len_th        = 0.0;
    2663:     petsc_isend_ct_th        = 0.0;
    2664:     petsc_irecv_ct_th        = 0.0;
    2665:     petsc_isend_len_th       = 0.0;
    2666:     petsc_irecv_len_th       = 0.0;
    2667:     petsc_wait_ct_th         = 0.0;
    2668:     petsc_wait_any_ct_th     = 0.0;
    2669:     petsc_wait_all_ct_th     = 0.0;
    2670:     petsc_sum_of_waits_ct_th = 0.0;
    2671:     petsc_allreduce_ct_th    = 0.0;
    2672:     petsc_gather_ct_th       = 0.0;
    2673:     petsc_scatter_ct_th      = 0.0;

    2675:     petsc_ctog_ct       = 0.0;
    2676:     petsc_gtoc_ct       = 0.0;
    2677:     petsc_ctog_sz       = 0.0;
    2678:     petsc_gtoc_sz       = 0.0;
    2679:     petsc_gflops        = 0.0;
    2680:     petsc_gtime         = 0.0;
    2681:     petsc_genergy       = 0.0;
    2682:     petsc_genergy_meter = 0.0;
    2683:     petsc_ctog_ct_th    = 0.0;
    2684:     petsc_gtoc_ct_th    = 0.0;
    2685:     petsc_ctog_sz_th    = 0.0;
    2686:     petsc_gtoc_sz_th    = 0.0;
    2687:     petsc_gflops_th     = 0.0;
    2688:     petsc_gtime_th      = 0.0;
    2689:   }
    2690:   PETSC_LARGEST_CLASSID    = PETSC_SMALLEST_CLASSID;
    2691:   PETSC_OBJECT_CLASSID     = 0;
    2692:   PetscLogInitializeCalled = PETSC_FALSE;
    2693:   PetscFunctionReturn(PETSC_SUCCESS);
    2694: }

    2696: /*@
    2697:   PetscClassIdRegister - Registers a new class name for objects and logging operations in an application code.

    2699:   Not Collective

    2701:   Input Parameter:
    2702: . name - The class name

    2704:   Output Parameter:
    2705: . oclass - The class id or classid

    2707:   Level: developer

    2709: .seealso: [](ch_profiling), `PetscLogEventRegister()`
    2710: @*/
    2711: PetscErrorCode PetscClassIdRegister(const char name[], PetscClassId *oclass)
    2712: {
    2713:   PetscFunctionBegin;
    2714:   *oclass = ++PETSC_LARGEST_CLASSID;
    2715: #if defined(PETSC_USE_LOG)
    2716:   {
    2717:     PetscLogState state;
    2718:     PetscLogClass logclass;

    2720:     PetscCall(PetscLogGetState(&state));
    2721:     if (state) PetscCall(PetscLogStateClassRegister(state, name, *oclass, &logclass));
    2722:   }
    2723: #endif
    2724:   PetscFunctionReturn(PETSC_SUCCESS);
    2725: }