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 */

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

 99: PetscBool PetscLogMemory = PETSC_FALSE;
100: PetscBool PetscLogSyncOn = PETSC_FALSE;

102: PetscBool PetscLogGpuTimeFlag = PETSC_FALSE;

104: PetscLogState petsc_log_state = NULL;

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

108: PetscLogHandlerHot PetscLogHandlers[PETSC_LOG_HANDLER_MAX] = {
109:   PETSC_LOG_HANDLER_HOT_BLANK,
110:   PETSC_LOG_HANDLER_HOT_BLANK,
111:   PETSC_LOG_HANDLER_HOT_BLANK,
112:   PETSC_LOG_HANDLER_HOT_BLANK,
113: };

115: #undef PETSC_LOG_HANDLERS_HOT_BLANK

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

120:   #if defined(PETSC_HAVE_THREADSAFETY)
121: PetscErrorCode PetscAddLogDouble(PetscLogDouble *tot, PetscLogDouble *tot_th, PetscLogDouble tmp)
122: {
123:   *tot_th += tmp;
124:   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
125:   *tot += tmp;
126:   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
127:   return PETSC_SUCCESS;
128: }

130: PetscErrorCode PetscAddLogDoubleCnt(PetscLogDouble *cnt, PetscLogDouble *tot, PetscLogDouble *cnt_th, PetscLogDouble *tot_th, PetscLogDouble tmp)
131: {
132:   *cnt_th = *cnt_th + 1;
133:   *tot_th += tmp;
134:   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
135:   *tot += (PetscLogDouble)tmp;
136:   *cnt += *cnt + 1;
137:   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
138:   return PETSC_SUCCESS;
139: }

141:   #endif

143: static PetscErrorCode PetscLogTryGetHandler(PetscLogHandlerType type, PetscLogHandler *handler)
144: {
145:   PetscFunctionBegin;
146:   PetscAssertPointer(handler, 2);
147:   *handler = NULL;
148:   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
149:     PetscLogHandler h = PetscLogHandlers[i].handler;
150:     if (h) {
151:       PetscBool match;

153:       PetscCall(PetscObjectTypeCompare((PetscObject)h, type, &match));
154:       if (match) {
155:         *handler = PetscLogHandlers[i].handler;
156:         PetscFunctionReturn(PETSC_SUCCESS);
157:       }
158:     }
159:   }
160:   PetscFunctionReturn(PETSC_SUCCESS);
161: }

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

166:   Not collective

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

171:   Level: developer

173:   Notes:
174:   The default handler is started with `PetscLogDefaultBegin()`,
175:   if the options flags `-log_all` or `-log_view` is given without arguments,
176:   or for `-log_view :output:format` if `format` is not `ascii_xml` or `ascii_flamegraph`.

178: .seealso: [](ch_profiling)
179: @*/
180: PetscErrorCode PetscLogGetDefaultHandler(PetscLogHandler *handler)
181: {
182:   PetscFunctionBegin;
183:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, handler));
184:   PetscFunctionReturn(PETSC_SUCCESS);
185: }

187: static PetscErrorCode PetscLogGetHandler(PetscLogHandlerType type, PetscLogHandler *handler)
188: {
189:   PetscFunctionBegin;
190:   PetscAssertPointer(handler, 2);
191:   PetscCall(PetscLogTryGetHandler(type, handler));
192:   PetscCheck(*handler != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "A PetscLogHandler of type %s has not been started.", type);
193:   PetscFunctionReturn(PETSC_SUCCESS);
194: }

196: /*@
197:   PetscLogGetState - Get the `PetscLogState` for PETSc's global logging, used
198:   by all default log handlers (`PetscLogDefaultBegin()`,
199:   `PetscLogNestedBegin()`, `PetscLogTraceBegin()`, `PetscLogMPEBegin()`,
200:   `PetscLogPerfstubsBegin()`).

202:   Collective on `PETSC_COMM_WORLD`

204:   Output Parameter:
205: . state - The `PetscLogState` changed by registrations (such as
206:           `PetscLogEventRegister()`) and actions (such as `PetscLogEventBegin()` or
207:           `PetscLogStagePush()`), or `NULL` if logging is not active

209:   Level: developer

211: .seealso: [](ch_profiling), `PetscLogState`
212: @*/
213: PetscErrorCode PetscLogGetState(PetscLogState *state)
214: {
215:   PetscFunctionBegin;
216:   PetscAssertPointer(state, 1);
217:   *state = petsc_log_state;
218:   PetscFunctionReturn(PETSC_SUCCESS);
219: }

221: static PetscErrorCode PetscLogHandlerCopyToHot(PetscLogHandler h, PetscLogHandlerHot *hot)
222: {
223:   PetscFunctionBegin;
224:   hot->handler       = h;
225:   hot->eventBegin    = h->ops->eventbegin;
226:   hot->eventEnd      = h->ops->eventend;
227:   hot->eventSync     = h->ops->eventsync;
228:   hot->objectCreate  = h->ops->objectcreate;
229:   hot->objectDestroy = h->ops->objectdestroy;
230:   PetscFunctionReturn(PETSC_SUCCESS);
231: }

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

236:   Logically collective

238:   Input Parameters:
239: . h - a `PetscLogHandler`

241:   Level: developer

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

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

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

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

257: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogState`, `PetscLogHandlerStop()`, `PetscInitialize()`
258: @*/
259: PetscErrorCode PetscLogHandlerStart(PetscLogHandler h)
260: {
261:   PetscFunctionBegin;
262:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
263:     if (PetscLogHandlers[i].handler == h) PetscFunctionReturn(PETSC_SUCCESS);
264:   }
265:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
266:     if (PetscLogHandlers[i].handler == NULL) {
267:       PetscCall(PetscObjectReference((PetscObject)h));
268:       PetscCall(PetscLogHandlerCopyToHot(h, &PetscLogHandlers[i]));
269:       if (petsc_log_state) {
270:         PetscLogStage stack_height;
271:         PetscIntStack orig_stack, temp_stack;

273:         PetscCall(PetscLogHandlerSetState(h, petsc_log_state));
274:         stack_height = petsc_log_state->stage_stack->top + 1;
275:         PetscCall(PetscIntStackCreate(&temp_stack));
276:         orig_stack                     = petsc_log_state->stage_stack;
277:         petsc_log_state->stage_stack   = temp_stack;
278:         petsc_log_state->current_stage = -1;
279:         for (int s = 0; s < stack_height; s++) {
280:           PetscLogStage stage = (PetscLogStage)orig_stack->stack[s];
281:           PetscCall(PetscLogHandlerStagePush(h, stage));
282:           PetscCall(PetscIntStackPush(temp_stack, stage));
283:           petsc_log_state->current_stage = stage;
284:         }
285:         PetscCall(PetscIntStackDestroy(temp_stack));
286:         petsc_log_state->stage_stack = orig_stack;
287:       }
288:       PetscFunctionReturn(PETSC_SUCCESS);
289:     }
290:   }
291:   SETERRQ(PetscObjectComm((PetscObject)h), PETSC_ERR_ARG_WRONGSTATE, "%d log handlers already started, cannot start another", PETSC_LOG_HANDLER_MAX);
292:   PetscFunctionReturn(PETSC_SUCCESS);
293: }

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

298:   Logically collective

300:   Input Parameters:
301: . h - a `PetscLogHandler`

303:   Level: developer

305:   Note:
306:   After `PetscLogHandlerStop()`, the handler can still access the global logging state
307:   with `PetscLogHandlerGetState()`, so that it can access the registry when post-processing
308:   (for instance, in `PetscLogHandlerView()`),

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

313: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogState`, `PetscLogHandlerStart()`
314: @*/
315: PetscErrorCode PetscLogHandlerStop(PetscLogHandler h)
316: {
317:   PetscFunctionBegin;
318:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
319:     if (PetscLogHandlers[i].handler == h) {
320:       if (petsc_log_state) {
321:         PetscLogState state;
322:         PetscLogStage stack_height;
323:         PetscIntStack orig_stack, temp_stack;

325:         PetscCall(PetscLogHandlerGetState(h, &state));
326:         PetscCheck(state == petsc_log_state, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "Called PetscLogHandlerStop() for a PetscLogHander that was not started.");
327:         stack_height = petsc_log_state->stage_stack->top + 1;
328:         PetscCall(PetscIntStackCreate(&temp_stack));
329:         orig_stack                   = petsc_log_state->stage_stack;
330:         petsc_log_state->stage_stack = temp_stack;
331:         for (int s = 0; s < stack_height; s++) {
332:           PetscLogStage stage = (PetscLogStage)orig_stack->stack[s];

334:           PetscCall(PetscIntStackPush(temp_stack, stage));
335:         }
336:         for (int s = 0; s < stack_height; s++) {
337:           PetscLogStage stage;
338:           PetscBool     empty;

340:           PetscCall(PetscIntStackPop(temp_stack, &stage));
341:           PetscCall(PetscIntStackEmpty(temp_stack, &empty));
342:           if (!empty) {
343:             PetscCall(PetscIntStackTop(temp_stack, &petsc_log_state->current_stage));
344:           } else petsc_log_state->current_stage = -1;
345:           PetscCall(PetscLogHandlerStagePop(h, stage));
346:         }
347:         PetscCall(PetscIntStackDestroy(temp_stack));
348:         petsc_log_state->stage_stack = orig_stack;
349:         PetscCall(PetscIntStackTop(petsc_log_state->stage_stack, &petsc_log_state->current_stage));
350:       }
351:       PetscCall(PetscArrayzero(&PetscLogHandlers[i], 1));
352:       PetscCall(PetscObjectDereference((PetscObject)h));
353:     }
354:   }
355:   PetscFunctionReturn(PETSC_SUCCESS);
356: }

358: /*@
359:   PetscLogIsActive - Check if logging is currently in progress.

361:   Not Collective

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

366:   Level: beginner

368: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`
369: @*/
370: PetscErrorCode PetscLogIsActive(PetscBool *isActive)
371: {
372:   PetscFunctionBegin;
373:   *isActive = PETSC_FALSE;
374:   if (petsc_log_state) {
375:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
376:       if (PetscLogHandlers[i].handler) {
377:         *isActive = PETSC_TRUE;
378:         PetscFunctionReturn(PETSC_SUCCESS);
379:       }
380:     }
381:   }
382:   PetscFunctionReturn(PETSC_SUCCESS);
383: }

385: PETSC_UNUSED static PetscErrorCode PetscLogEventBeginIsActive(PetscBool *isActive)
386: {
387:   PetscFunctionBegin;
388:   *isActive = PETSC_FALSE;
389:   if (petsc_log_state) {
390:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
391:       if (PetscLogHandlers[i].eventBegin) {
392:         *isActive = PETSC_TRUE;
393:         PetscFunctionReturn(PETSC_SUCCESS);
394:       }
395:     }
396:   }
397:   PetscFunctionReturn(PETSC_SUCCESS);
398: }

400: PETSC_UNUSED static PetscErrorCode PetscLogEventEndIsActive(PetscBool *isActive)
401: {
402:   PetscFunctionBegin;
403:   *isActive = PETSC_FALSE;
404:   if (petsc_log_state) {
405:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
406:       if (PetscLogHandlers[i].eventEnd) {
407:         *isActive = PETSC_TRUE;
408:         PetscFunctionReturn(PETSC_SUCCESS);
409:       }
410:     }
411:   }
412:   PetscFunctionReturn(PETSC_SUCCESS);
413: }

415: PETSC_INTERN PetscErrorCode PetscLogTypeBegin(PetscLogHandlerType type)
416: {
417:   PetscLogHandler handler;

419:   PetscFunctionBegin;
420:   PetscCall(PetscLogTryGetHandler(type, &handler));
421:   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
422:   PetscCall(PetscLogHandlerCreate(PETSC_COMM_WORLD, &handler));
423:   PetscCall(PetscLogHandlerSetType(handler, type));
424:   PetscCall(PetscLogHandlerStart(handler));
425:   PetscCall(PetscLogHandlerDestroy(&handler));
426:   PetscFunctionReturn(PETSC_SUCCESS);
427: }

429: /*@
430:   PetscLogDefaultBegin - Turns on logging of objects and events using the default log handler. This logs flop
431:   rates and object creation and should not slow programs down too much.
432:   This routine may be called more than once.

434:   Logically Collective on `PETSC_COMM_WORLD`

436:   Options Database Key:
437: . -log_view [viewertype:filename:viewerformat] - Prints summary of flop and timing information to the
438:                                                  screen (for code configured with --with-log=1 (which is the default))

440:   Example Usage:
441: .vb
442:       PetscInitialize(...);
443:       PetscLogDefaultBegin();
444:        ... code ...
445:       PetscLogView(viewer); or PetscLogDump();
446:       PetscFinalize();
447: .ve

449:   Level: advanced

451:   Note:
452:   `PetscLogView()` or `PetscLogDump()` actually cause the printing of
453:   the logging information.

455: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`
456: @*/
457: PetscErrorCode PetscLogDefaultBegin(void)
458: {
459:   PetscFunctionBegin;
460:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERDEFAULT));
461:   PetscFunctionReturn(PETSC_SUCCESS);
462: }

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

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

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

473:   Options Database Key:
474: . -log_trace [filename] - Begins `PetscLogTraceBegin()`

476:   Level: intermediate

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

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

486: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogDefaultBegin()`
487: @*/
488: PetscErrorCode PetscLogTraceBegin(FILE *file)
489: {
490:   PetscLogHandler handler;

492:   PetscFunctionBegin;
493:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERTRACE, &handler));
494:   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
495:   PetscCall(PetscLogHandlerCreateTrace(PETSC_COMM_WORLD, file, &handler));
496:   PetscCall(PetscLogHandlerStart(handler));
497:   PetscCall(PetscLogHandlerDestroy(&handler));
498:   PetscFunctionReturn(PETSC_SUCCESS);
499: }

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

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

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

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

512:   Example Usage:
513: .vb
514:       PetscInitialize(...);
515:       PetscLogNestedBegin();
516:        ... code ...
517:       PetscLogView(viewer);
518:       PetscFinalize();
519: .ve

521:   Level: advanced

523: .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`
524: @*/
525: PetscErrorCode PetscLogNestedBegin(void)
526: {
527:   PetscFunctionBegin;
528:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERNESTED));
529:   PetscFunctionReturn(PETSC_SUCCESS);
530: }

532: /*@C
533:   PetscLogLegacyCallbacksBegin - Create and start a log handler from callbacks
534:   matching the now deprecated function pointers `PetscLogPLB`, `PetscLogPLE`,
535:   `PetscLogPHC`, `PetscLogPHD`.

537:   Logically Collective on `PETSC_COMM_WORLD`

539:   Input Parameters:
540: + PetscLogPLB - A callback that will be executed by `PetscLogEventBegin()` (or `NULL`)
541: . PetscLogPLE - A callback that will be executed by `PetscLogEventEnd()` (or `NULL`)
542: . PetscLogPHC - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)
543: - PetscLogPHD - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)

545:   Calling sequence of `PetscLogPLB`:
546: + e  - a `PetscLogEvent` that is beginning
547: . _i - deprecated, unused
548: . o1 - a `PetscObject` associated with `e` (or `NULL`)
549: . o2 - a `PetscObject` associated with `e` (or `NULL`)
550: . o3 - a `PetscObject` associated with `e` (or `NULL`)
551: - o4 - a `PetscObject` associated with `e` (or `NULL`)

553:   Calling sequence of `PetscLogPLE`:
554: + e  - a `PetscLogEvent` that is beginning
555: . _i - deprecated, unused
556: . o1 - a `PetscObject` associated with `e` (or `NULL`)
557: . o2 - a `PetscObject` associated with `e` (or `NULL`)
558: . o3 - a `PetscObject` associated with `e` (or `NULL`)
559: - o4 - a `PetscObject` associated with `e` (or `NULL`)

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

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

567:   Level: advanced

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

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

576: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogHandlerStart()`, `PetscLogState`
577: @*/
578: 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))
579: {
580:   PetscLogHandler handler;

582:   PetscFunctionBegin;
583:   PetscCall(PetscLogHandlerCreateLegacy(PETSC_COMM_WORLD, PetscLogPLB, PetscLogPLE, PetscLogPHC, PetscLogPHD, &handler));
584:   PetscCall(PetscLogHandlerStart(handler));
585:   PetscCall(PetscLogHandlerDestroy(&handler));
586:   PetscFunctionReturn(PETSC_SUCCESS);
587: }

589:   #if defined(PETSC_HAVE_MPE)
590:     #include <mpe.h>
591: static PetscBool PetscBeganMPE = PETSC_FALSE;
592:   #endif

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

598:   Collective on `PETSC_COMM_WORLD`, No Fortran Support

600:   Options Database Key:
601: . -log_mpe - Prints extensive log information

603:   Level: advanced

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

610: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogDefaultBegin()`, `PetscLogEventActivate()`,
611:           `PetscLogEventDeactivate()`
612: @*/
613: PetscErrorCode PetscLogMPEBegin(void)
614: {
615:   PetscFunctionBegin;
616:   #if defined(PETSC_HAVE_MPE)
617:   /* Do MPE initialization */
618:   if (!MPE_Initialized_logging()) { /* This function exists in mpich 1.1.2 and higher */
619:     PetscCall(PetscInfo(0, "Initializing MPE.\n"));
620:     PetscCall(MPE_Init_log());

622:     PetscBeganMPE = PETSC_TRUE;
623:   } else {
624:     PetscCall(PetscInfo(0, "MPE already initialized. Not attempting to reinitialize.\n"));
625:   }
626:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERMPE));
627:   #else
628:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
629:   #endif
630:   PetscFunctionReturn(PETSC_SUCCESS);
631: }

633:   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
634: #include <../src/sys/perfstubs/timer.h>
635:   #endif

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

640:   Collective on `PETSC_COMM_WORLD`, No Fortran Support

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

645:   Level: advanced

647: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogEventActivate()`
648: @*/
649: PetscErrorCode PetscLogPerfstubsBegin(void)
650: {
651:   PetscFunctionBegin;
652:   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
653:   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERPERFSTUBS));
654:   #else
655:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without perfstubs support, reconfigure with --with-tau-perfstubs");
656:   #endif
657:   PetscFunctionReturn(PETSC_SUCCESS);
658: }

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

663:   Not Collective

665:   Input Parameter:
666: . flag - `PETSC_TRUE` if actions are to be logged

668:   Options Database Key:
669: + -log_exclude_actions - (deprecated) Does nothing
670: - -log_include_actions - Turn on action logging

672:   Level: intermediate

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

678: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogGetDefaultHandler()`
679: @*/
680: PetscErrorCode PetscLogActions(PetscBool flag)
681: {
682:   PetscFunctionBegin;
683:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
684:     PetscLogHandler h = PetscLogHandlers[i].handler;

686:     if (h) PetscCall(PetscLogHandlerSetLogActions(h, flag));
687:   }
688:   PetscFunctionReturn(PETSC_SUCCESS);
689: }

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

694:   Not Collective

696:   Input Parameter:
697: . flag - `PETSC_TRUE` if objects are to be logged

699:   Options Database Key:
700: + -log_exclude_objects - (deprecated) Does nothing
701: - -log_include_objects - Turns on object logging

703:   Level: intermediate

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

709: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogGetDefaultHandler()`
710: @*/
711: PetscErrorCode PetscLogObjects(PetscBool flag)
712: {
713:   PetscFunctionBegin;
714:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
715:     PetscLogHandler h = PetscLogHandlers[i].handler;

717:     if (h) PetscCall(PetscLogHandlerSetLogObjects(h, flag));
718:   }
719:   PetscFunctionReturn(PETSC_SUCCESS);
720: }

722: /*------------------------------------------------ Stage Functions --------------------------------------------------*/
723: /*@
724:   PetscLogStageRegister - Attaches a character string name to a logging stage.

726:   Not Collective

728:   Input Parameter:
729: . sname - The name to associate with that stage

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

734:   Level: intermediate

736: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`
737: @*/
738: PetscErrorCode PetscLogStageRegister(const char sname[], PetscLogStage *stage)
739: {
740:   PetscLogState state;

742:   PetscFunctionBegin;
743:   *stage = -1;
744:   PetscCall(PetscLogGetState(&state));
745:   if (state) PetscCall(PetscLogStateStageRegister(state, sname, stage));
746:   PetscFunctionReturn(PETSC_SUCCESS);
747: }

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

752:   Not Collective

754:   Input Parameter:
755: . stage - The stage on which to log

757:   Example Usage:
758:   If the option -log_view is used to run the program containing the
759:   following code, then 2 sets of summary data will be printed during
760:   PetscFinalize().
761: .vb
762:       PetscInitialize(int *argc,char ***args,0,0);
763:       [stage 0 of code]
764:       PetscLogStagePush(1);
765:       [stage 1 of code]
766:       PetscLogStagePop();
767:       PetscBarrier(...);
768:       [more stage 0 of code]
769:       PetscFinalize();
770: .ve

772:   Level: intermediate

774:   Note:
775:   Use `PetscLogStageRegister()` to register a stage.

777: .seealso: [](ch_profiling), `PetscLogStagePop()`, `PetscLogStageRegister()`, `PetscBarrier()`
778: @*/
779: PetscErrorCode PetscLogStagePush(PetscLogStage stage)
780: {
781:   PetscLogState state;

783:   PetscFunctionBegin;
784:   PetscCall(PetscLogGetState(&state));
785:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
786:   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
787:     PetscLogHandler h = PetscLogHandlers[i].handler;
788:     if (h) PetscCall(PetscLogHandlerStagePush(h, stage));
789:   }
790:   PetscCall(PetscLogStateStagePush(state, stage));
791:   PetscFunctionReturn(PETSC_SUCCESS);
792: }

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

797:   Not Collective

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

814:   Level: intermediate

816: .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStageRegister()`, `PetscBarrier()`
817: @*/
818: PetscErrorCode PetscLogStagePop(void)
819: {
820:   PetscLogState state;
821:   PetscLogStage current_stage;

823:   PetscFunctionBegin;
824:   PetscCall(PetscLogGetState(&state));
825:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
826:   current_stage = state->current_stage;
827:   PetscCall(PetscLogStateStagePop(state));
828:   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
829:     PetscLogHandler h = PetscLogHandlers[i].handler;
830:     if (h) PetscCall(PetscLogHandlerStagePop(h, current_stage));
831:   }
832:   PetscFunctionReturn(PETSC_SUCCESS);
833: }

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

838:   Not Collective

840:   Input Parameters:
841: + stage    - The stage
842: - isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)

844:   Level: intermediate

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

849: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
850: @*/
851: PetscErrorCode PetscLogStageSetActive(PetscLogStage stage, PetscBool isActive)
852: {
853:   PetscLogState state;

855:   PetscFunctionBegin;
856:   PetscCall(PetscLogGetState(&state));
857:   if (state) PetscCall(PetscLogStateStageSetActive(state, stage, isActive));
858:   PetscFunctionReturn(PETSC_SUCCESS);
859: }

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

864:   Not Collective

866:   Input Parameter:
867: . stage - The stage

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

872:   Level: intermediate

874: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
875: @*/
876: PetscErrorCode PetscLogStageGetActive(PetscLogStage stage, PetscBool *isActive)
877: {
878:   PetscLogState state;

880:   PetscFunctionBegin;
881:   *isActive = PETSC_FALSE;
882:   PetscCall(PetscLogGetState(&state));
883:   if (state) PetscCall(PetscLogStateStageGetActive(state, stage, isActive));
884:   PetscFunctionReturn(PETSC_SUCCESS);
885: }

887: /*@
888:   PetscLogStageSetVisible - Determines stage visibility in `PetscLogView()`

890:   Not Collective

892:   Input Parameters:
893: + stage     - The stage
894: - isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)

896:   Level: intermediate

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

902: .seealso: [](ch_profiling), `PetscLogStageGetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
903: @*/
904: PetscErrorCode PetscLogStageSetVisible(PetscLogStage stage, PetscBool isVisible)

906: {
907:   PetscFunctionBegin;
908:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
909:     PetscLogHandler h = PetscLogHandlers[i].handler;

911:     if (h) PetscCall(PetscLogHandlerStageSetVisible(h, stage, isVisible));
912:   }
913:   PetscFunctionReturn(PETSC_SUCCESS);
914: }

916: /*@
917:   PetscLogStageGetVisible - Returns stage visibility in `PetscLogView()`

919:   Not Collective

921:   Input Parameter:
922: . stage - The stage

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

927:   Level: intermediate

929: .seealso: [](ch_profiling), `PetscLogStageSetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
930: @*/
931: PetscErrorCode PetscLogStageGetVisible(PetscLogStage stage, PetscBool *isVisible)
932: {
933:   PetscLogHandler handler;

935:   PetscFunctionBegin;
936:   *isVisible = PETSC_FALSE;
937:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
938:   if (handler) { PetscCall(PetscLogHandlerStageGetVisible(handler, stage, isVisible)); }
939:   PetscFunctionReturn(PETSC_SUCCESS);
940: }

942: /*@
943:   PetscLogStageGetId - Returns the stage id when given the stage name.

945:   Not Collective

947:   Input Parameter:
948: . name - The stage name

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

953:   Level: intermediate

955: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
956: @*/
957: PetscErrorCode PetscLogStageGetId(const char name[], PetscLogStage *stage)
958: {
959:   PetscLogState state;

961:   PetscFunctionBegin;
962:   *stage = -1;
963:   PetscCall(PetscLogGetState(&state));
964:   if (state) PetscCall(PetscLogStateGetStageFromName(state, name, stage));
965:   PetscFunctionReturn(PETSC_SUCCESS);
966: }

968: /*@
969:   PetscLogStageGetName - Returns the stage name when given the stage id.

971:   Not Collective

973:   Input Parameter:
974: . stage - The stage

976:   Output Parameter:
977: . name - The stage name

979:   Level: intermediate

981: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
982: @*/
983: PetscErrorCode PetscLogStageGetName(PetscLogStage stage, const char *name[])
984: {
985:   PetscLogStageInfo stage_info;
986:   PetscLogState     state;

988:   PetscFunctionBegin;
989:   *name = NULL;
990:   PetscCall(PetscLogGetState(&state));
991:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
992:   PetscCall(PetscLogStateStageGetInfo(state, stage, &stage_info));
993:   *name = stage_info.name;
994:   PetscFunctionReturn(PETSC_SUCCESS);
995: }

997: /*------------------------------------------------ Event Functions --------------------------------------------------*/

999: /*@
1000:   PetscLogEventRegister - Registers an event name for logging operations

1002:   Not Collective

1004:   Input Parameters:
1005: + name    - The name associated with the event
1006: - classid - The classid associated to the class for this event, obtain either with
1007:            `PetscClassIdRegister()` or use a predefined one such as `KSP_CLASSID`, `SNES_CLASSID`, the predefined ones
1008:            are only available in C code

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

1013:   Example Usage:
1014: .vb
1015:       PetscLogEvent USER_EVENT;
1016:       PetscClassId classid;
1017:       PetscLogDouble user_event_flops;
1018:       PetscClassIdRegister("class name",&classid);
1019:       PetscLogEventRegister("User event name",classid,&USER_EVENT);
1020:       PetscLogEventBegin(USER_EVENT,0,0,0,0);
1021:          [code segment to monitor]
1022:          PetscLogFlops(user_event_flops);
1023:       PetscLogEventEnd(USER_EVENT,0,0,0,0);
1024: .ve

1026:   Level: intermediate

1028:   Notes:
1029:   PETSc automatically logs library events if the code has been
1030:   configured with --with-log (which is the default) and
1031:   -log_view or -log_all is specified.  `PetscLogEventRegister()` is
1032:   intended for logging user events to supplement this PETSc
1033:   information.

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

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

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

1050: .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogFlops()`,
1051:           `PetscLogEventActivate()`, `PetscLogEventDeactivate()`, `PetscClassIdRegister()`
1052: @*/
1053: PetscErrorCode PetscLogEventRegister(const char name[], PetscClassId classid, PetscLogEvent *event)
1054: {
1055:   PetscLogState state;

1057:   PetscFunctionBegin;
1058:   *event = -1;
1059:   PetscCall(PetscLogGetState(&state));
1060:   if (state) PetscCall(PetscLogStateEventRegister(state, name, classid, event));
1061:   PetscFunctionReturn(PETSC_SUCCESS);
1062: }

1064: /*@
1065:   PetscLogEventSetCollective - Indicates that a particular event is collective.

1067:   Logically Collective

1069:   Input Parameters:
1070: + event      - The event id
1071: - collective - `PetscBool` indicating whether a particular event is collective

1073:   Level: developer

1075:   Notes:
1076:   New events returned from `PetscLogEventRegister()` are collective by default.

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

1082: .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogEventRegister()`
1083: @*/
1084: PetscErrorCode PetscLogEventSetCollective(PetscLogEvent event, PetscBool collective)
1085: {
1086:   PetscLogState state;

1088:   PetscFunctionBegin;
1089:   PetscCall(PetscLogGetState(&state));
1090:   if (state) PetscCall(PetscLogStateEventSetCollective(state, event, collective));
1091:   PetscFunctionReturn(PETSC_SUCCESS);
1092: }

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

1097:   Not Collective

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

1103:   Level: developer

1105: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`, `PetscLogEventActivateClass()`
1106: */
1107: static PetscErrorCode PetscLogClassSetActiveAll(PetscClassId classid, PetscBool isActive)
1108: {
1109:   PetscLogState state;

1111:   PetscFunctionBegin;
1112:   PetscCall(PetscLogGetState(&state));
1113:   if (state) PetscCall(PetscLogStateClassSetActiveAll(state, classid, isActive));
1114:   PetscFunctionReturn(PETSC_SUCCESS);
1115: }

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

1120:   Not Collective

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

1125:   Level: developer

1127: .seealso: [](ch_profiling), `PetscLogEventActivateClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1128: @*/
1129: PetscErrorCode PetscLogEventIncludeClass(PetscClassId classid)
1130: {
1131:   PetscFunctionBegin;
1132:   PetscCall(PetscLogClassSetActiveAll(classid, PETSC_TRUE));
1133:   PetscFunctionReturn(PETSC_SUCCESS);
1134: }

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

1139:   Not Collective

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

1144:   Level: developer

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

1149: .seealso: [](ch_profiling), `PetscLogEventDeactivateClass()`, `PetscLogEventActivateClass()`, `PetscLogEventDeactivate()`, `PetscLogEventActivate()`
1150: @*/
1151: PetscErrorCode PetscLogEventExcludeClass(PetscClassId classid)
1152: {
1153:   PetscFunctionBegin;
1154:   PetscCall(PetscLogClassSetActiveAll(classid, PETSC_FALSE));
1155:   PetscFunctionReturn(PETSC_SUCCESS);
1156: }

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

1161:   Not Collective

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

1168:   Usage:
1169: .vb
1170:       PetscLogEventSetActive(VEC_SetValues, PETSC_FALSE);
1171:         [code where you do not want to log VecSetValues()]
1172:       PetscLogEventSetActive(VEC_SetValues, PETSC_TRUE);
1173:         [code where you do want to log VecSetValues()]
1174: .ve

1176:   Level: advanced

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

1182: .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1183: */
1184: static PetscErrorCode PetscLogEventSetActive(PetscLogStage stage, PetscLogEvent event, PetscBool isActive)
1185: {
1186:   PetscLogState state;

1188:   PetscFunctionBegin;
1189:   PetscCall(PetscLogGetState(&state));
1190:   if (state) PetscCall(PetscLogStateEventSetActive(state, stage, event, isActive));
1191:   PetscFunctionReturn(PETSC_SUCCESS);
1192: }

1194: /*@
1195:   PetscLogEventActivate - Indicates that a particular event should be logged.

1197:   Not Collective

1199:   Input Parameter:
1200: . event - The event id

1202:   Example Usage:
1203: .vb
1204:       PetscLogEventDeactivate(VEC_SetValues);
1205:         [code where you do not want to log VecSetValues()]
1206:       PetscLogEventActivate(VEC_SetValues);
1207:         [code where you do want to log VecSetValues()]
1208: .ve

1210:   Level: advanced

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

1216: .seealso: [](ch_profiling), `PetscLogEventDeactivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1217: @*/
1218: PetscErrorCode PetscLogEventActivate(PetscLogEvent event)
1219: {
1220:   PetscFunctionBegin;
1221:   PetscCall(PetscLogEventSetActive(PETSC_DEFAULT, event, PETSC_TRUE));
1222:   PetscFunctionReturn(PETSC_SUCCESS);
1223: }

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

1228:   Not Collective

1230:   Input Parameter:
1231: . event - The event id

1233:   Example Usage:
1234: .vb
1235:       PetscLogEventDeactivate(VEC_SetValues);
1236:         [code where you do not want to log VecSetValues()]
1237:       PetscLogEventActivate(VEC_SetValues);
1238:         [code where you do want to log VecSetValues()]
1239: .ve

1241:   Level: advanced

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

1247: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1248: @*/
1249: PetscErrorCode PetscLogEventDeactivate(PetscLogEvent event)
1250: {
1251:   PetscFunctionBegin;
1252:   PetscCall(PetscLogEventSetActive(PETSC_DEFAULT, event, PETSC_FALSE));
1253:   PetscFunctionReturn(PETSC_SUCCESS);
1254: }

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

1259:   Not Collective

1261:   Input Parameter:
1262: . event - The event id

1264:   Example Usage:
1265: .vb
1266:       PetscLogEventDeactivatePush(VEC_SetValues);
1267:         [code where you do not want to log VecSetValues()]
1268:       PetscLogEventDeactivatePop(VEC_SetValues);
1269:         [code where you do want to log VecSetValues()]
1270: .ve

1272:   Level: advanced

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

1278:   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.

1280: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivate()`, `PetscLogEventDeactivatePop()`
1281: @*/
1282: PetscErrorCode PetscLogEventDeactivatePush(PetscLogEvent event)
1283: {
1284:   PetscFunctionBegin;
1285:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1286:     PetscLogHandler h = PetscLogHandlers[i].handler;

1288:     if (h) PetscCall(PetscLogHandlerEventDeactivatePush(h, PETSC_DEFAULT, event));
1289:   }
1290:   PetscFunctionReturn(PETSC_SUCCESS);
1291: }

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

1296:   Not Collective

1298:   Input Parameter:
1299: . event - The event id

1301:   Example Usage:
1302: .vb
1303:       PetscLogEventDeactivatePush(VEC_SetValues);
1304:         [code where you do not want to log VecSetValues()]
1305:       PetscLogEventDeactivatePop(VEC_SetValues);
1306:         [code where you do want to log VecSetValues()]
1307: .ve

1309:   Level: advanced

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

1315: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`
1316: @*/
1317: PetscErrorCode PetscLogEventDeactivatePop(PetscLogEvent event)
1318: {
1319:   PetscFunctionBegin;
1320:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1321:     PetscLogHandler h = PetscLogHandlers[i].handler;

1323:     if (h) PetscCall(PetscLogHandlerEventDeactivatePop(h, PETSC_DEFAULT, event));
1324:   }
1325:   PetscFunctionReturn(PETSC_SUCCESS);
1326: }

1328: /*@
1329:   PetscLogEventSetActiveAll - Turns on logging of all events

1331:   Not Collective

1333:   Input Parameters:
1334: + event    - The event id
1335: - isActive - The activity flag determining whether the event is logged

1337:   Level: advanced

1339: .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1340: @*/
1341: PetscErrorCode PetscLogEventSetActiveAll(PetscLogEvent event, PetscBool isActive)
1342: {
1343:   PetscLogState state;

1345:   PetscFunctionBegin;
1346:   PetscCall(PetscLogGetState(&state));
1347:   if (state) PetscCall(PetscLogStateEventSetActiveAll(state, event, isActive));
1348:   PetscFunctionReturn(PETSC_SUCCESS);
1349: }

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

1354:   Not Collective

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

1361:   Level: developer

1363: .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`
1364: */
1365: static PetscErrorCode PetscLogClassSetActive(PetscLogStage stage, PetscClassId classid, PetscBool isActive)
1366: {
1367:   PetscLogState state;

1369:   PetscFunctionBegin;
1370:   PetscCall(PetscLogGetState(&state));
1371:   if (state) PetscCall(PetscLogStateClassSetActive(state, stage, classid, isActive));
1372:   PetscFunctionReturn(PETSC_SUCCESS);
1373: }

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

1378:   Not Collective

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

1383:   Level: developer

1385: .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1386: @*/
1387: PetscErrorCode PetscLogEventActivateClass(PetscClassId classid)
1388: {
1389:   PetscFunctionBegin;
1390:   PetscCall(PetscLogClassSetActive(PETSC_DEFAULT, classid, PETSC_TRUE));
1391:   PetscFunctionReturn(PETSC_SUCCESS);
1392: }

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

1397:   Not Collective

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

1402:   Level: developer

1404: .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventActivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1405: @*/
1406: PetscErrorCode PetscLogEventDeactivateClass(PetscClassId classid)
1407: {
1408:   PetscFunctionBegin;
1409:   PetscCall(PetscLogClassSetActive(PETSC_DEFAULT, classid, PETSC_FALSE));
1410:   PetscFunctionReturn(PETSC_SUCCESS);
1411: }

1413: /*MC
1414:   PetscLogEventSync - Synchronizes the beginning of a user event.

1416:   Synopsis:
1417: #include <petsclog.h>
1418:   PetscErrorCode PetscLogEventSync(PetscLogEvent e, MPI_Comm comm)

1420:   Collective

1422:   Input Parameters:
1423: + e    - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1424: - comm - an MPI communicator

1426:   Example Usage:
1427: .vb
1428:   PetscLogEvent USER_EVENT;

1430:   PetscLogEventRegister("User event", 0, &USER_EVENT);
1431:   PetscLogEventSync(USER_EVENT, PETSC_COMM_WORLD);
1432:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1433:   [code segment to monitor]
1434:   PetscLogEventEnd(USER_EVENT, 0, 0, 0 , 0);
1435: .ve

1437:   Level: developer

1439:   Note:
1440:   This routine should be called only if there is not a `PetscObject` available to pass to
1441:   `PetscLogEventBegin()`.

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

1446: /*MC
1447:   PetscLogEventBegin - Logs the beginning of a user event.

1449:   Synopsis:
1450: #include <petsclog.h>
1451:   PetscErrorCode PetscLogEventBegin(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)

1453:   Not Collective

1455:   Input Parameters:
1456: + e  - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1457: . o1 - object associated with the event, or `NULL`
1458: . o2 - object associated with the event, or `NULL`
1459: . o3 - object associated with the event, or `NULL`
1460: - o4 - object associated with the event, or `NULL`

1462:   Fortran Synopsis:
1463:   void PetscLogEventBegin(int e, PetscErrorCode ierr)

1465:   Example Usage:
1466: .vb
1467:   PetscLogEvent USER_EVENT;

1469:   PetscLogDouble user_event_flops;
1470:   PetscLogEventRegister("User event",0, &USER_EVENT);
1471:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1472:   [code segment to monitor]
1473:   PetscLogFlops(user_event_flops);
1474:   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
1475: .ve

1477:   Level: intermediate

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

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

1488: /*MC
1489:   PetscLogEventEnd - Log the end of a user event.

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

1495:   Not Collective

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

1504:   Fortran Synopsis:
1505:   void PetscLogEventEnd(int e, PetscErrorCode ierr)

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

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

1519:   Level: intermediate

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

1524: /*@C
1525:   PetscLogStageGetPerfInfo - Return the performance information about the given stage

1527:   No Fortran Support

1529:   Input Parameters:
1530: . stage - The stage number or `PETSC_DETERMINE` for the current stage

1532:   Output Parameter:
1533: . info - This structure is filled with the performance information

1535:   Level: intermediate

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

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

1544: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogGetDefaultHandler()`
1545: @*/
1546: PetscErrorCode PetscLogStageGetPerfInfo(PetscLogStage stage, PetscEventPerfInfo *info)
1547: {
1548:   PetscLogHandler     handler;
1549:   PetscEventPerfInfo *event_info;

1551:   PetscFunctionBegin;
1552:   PetscAssertPointer(info, 2);
1553:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1554:   if (handler) {
1555:     PetscCall(PetscLogHandlerGetStagePerfInfo(handler, stage, &event_info));
1556:     *info = *event_info;
1557:   } else {
1558:     PetscCall(PetscInfo(NULL, "Default log handler is not running, PetscLogStageGetPerfInfo() returning zeros\n"));
1559:     PetscCall(PetscMemzero(info, sizeof(*info)));
1560:   }
1561:   PetscFunctionReturn(PETSC_SUCCESS);
1562: }

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

1567:   No Fortran Support

1569:   Input Parameters:
1570: + stage - The stage number or `PETSC_DETERMINE` for the current stage
1571: - event - The event number

1573:   Output Parameter:
1574: . info - This structure is filled with the performance information

1576:   Level: intermediate

1578:   Note:
1579:   This is a low level routine used by the logging functions in PETSc

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

1585: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogGetDefaultHandler()`
1586: @*/
1587: PetscErrorCode PetscLogEventGetPerfInfo(PetscLogStage stage, PetscLogEvent event, PetscEventPerfInfo *info)
1588: {
1589:   PetscLogHandler     handler;
1590:   PetscEventPerfInfo *event_info;

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

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

1608:   Not Collective

1610:   Input Parameters:
1611: + event - The event id to log
1612: . n     - The dof index, in [0, 8)
1613: - dof   - The number of dofs

1615:   Options Database Key:
1616: . -log_view - Activates log summary

1618:   Level: developer

1620:   Note:
1621:   This is to enable logging of convergence

1623: .seealso: `PetscLogEventSetError()`, `PetscLogEventRegister()`, `PetscLogGetDefaultHandler()`
1624: @*/
1625: PetscErrorCode PetscLogEventSetDof(PetscLogEvent event, PetscInt n, PetscLogDouble dof)
1626: {
1627:   PetscFunctionBegin;
1628:   PetscCheck(!(n < 0) && !(n > 7), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Error index %" PetscInt_FMT " is not in [0, 8)", n);
1629:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1630:     PetscLogHandler h = PetscLogHandlers[i].handler;

1632:     if (h) {
1633:       PetscEventPerfInfo *event_info;

1635:       PetscCall(PetscLogHandlerGetEventPerfInfo(h, PETSC_DEFAULT, event, &event_info));
1636:       if (event_info) event_info->dof[n] = dof;
1637:     }
1638:   }
1639:   PetscFunctionReturn(PETSC_SUCCESS);
1640: }

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

1645:   Not Collective

1647:   Input Parameters:
1648: + event - The event id to log
1649: . n     - The error index, in [0, 8)
1650: - error - The error

1652:   Options Database Key:
1653: . -log_view - Activates log summary

1655:   Level: developer

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

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

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

1672:     if (h) {
1673:       PetscEventPerfInfo *event_info;

1675:       PetscCall(PetscLogHandlerGetEventPerfInfo(h, PETSC_DEFAULT, event, &event_info));
1676:       if (event_info) event_info->errors[n] = error;
1677:     }
1678:   }
1679:   PetscFunctionReturn(PETSC_SUCCESS);
1680: }

1682: /*@
1683:   PetscLogEventGetId - Returns the event id when given the event name.

1685:   Not Collective

1687:   Input Parameter:
1688: . name - The event name

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

1693:   Level: intermediate

1695: .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1696: @*/
1697: PetscErrorCode PetscLogEventGetId(const char name[], PetscLogEvent *event)
1698: {
1699:   PetscLogState state;

1701:   PetscFunctionBegin;
1702:   *event = -1;
1703:   PetscCall(PetscLogGetState(&state));
1704:   if (state) PetscCall(PetscLogStateGetEventFromName(state, name, event));
1705:   PetscFunctionReturn(PETSC_SUCCESS);
1706: }

1708: /*@
1709:   PetscLogEventGetName - Returns the event name when given the event id.

1711:   Not Collective

1713:   Input Parameter:
1714: . event - The event

1716:   Output Parameter:
1717: . name - The event name

1719:   Level: intermediate

1721: .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
1722: @*/
1723: PetscErrorCode PetscLogEventGetName(PetscLogEvent event, const char *name[])
1724: {
1725:   PetscLogEventInfo event_info;
1726:   PetscLogState     state;

1728:   PetscFunctionBegin;
1729:   *name = NULL;
1730:   PetscCall(PetscLogGetState(&state));
1731:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
1732:   PetscCall(PetscLogStateEventGetInfo(state, event, &event_info));
1733:   *name = event_info.name;
1734:   PetscFunctionReturn(PETSC_SUCCESS);
1735: }

1737: /*@
1738:   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.

1740:   Not collective

1742:   Level: advanced

1744:   Notes:
1745:   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()`).

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

1749: .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsResume()`, `PetscLogGetDefaultHandler()`
1750: @*/
1751: PetscErrorCode PetscLogEventsPause(void)
1752: {
1753:   PetscFunctionBegin;
1754:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1755:     PetscLogHandler h = PetscLogHandlers[i].handler;

1757:     if (h) PetscCall(PetscLogHandlerEventsPause(h));
1758:   }
1759:   PetscFunctionReturn(PETSC_SUCCESS);
1760: }

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

1765:   Not collective

1767:   Level: advanced

1769: .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsPause()`, `PetscLogGetDefaultHandler()`
1770: @*/
1771: PetscErrorCode PetscLogEventsResume(void)
1772: {
1773:   PetscFunctionBegin;
1774:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1775:     PetscLogHandler h = PetscLogHandlers[i].handler;

1777:     if (h) PetscCall(PetscLogHandlerEventsResume(h));
1778:   }
1779:   PetscFunctionReturn(PETSC_SUCCESS);
1780: }

1782: /*------------------------------------------------ Class Functions --------------------------------------------------*/

1784: /*MC
1785:    PetscLogObjectCreate - Log the creation of a `PetscObject`

1787:    Synopsis:
1788: #include <petsclog.h>
1789:    PetscErrorCode PetscLogObjectCreate(PetscObject h)

1791:    Not Collective

1793:    Input Parameters:
1794: .  h - A `PetscObject`

1796:    Level: developer

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

1802: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectDestroy()`
1803: M*/

1805: /*MC
1806:    PetscLogObjectDestroy - Logs the destruction of a `PetscObject`

1808:    Synopsis:
1809: #include <petsclog.h>
1810:    PetscErrorCode PetscLogObjectDestroy(PetscObject h)

1812:    Not Collective

1814:    Input Parameters:
1815: .  h - A `PetscObject`

1817:    Level: developer

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

1823: .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectCreate()`
1824: M*/

1826: /*@
1827:   PetscLogClassGetClassId - Returns the `PetscClassId` when given the class name.

1829:   Not Collective

1831:   Input Parameter:
1832: . name - The class name

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

1837:   Level: intermediate

1839: .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1840: @*/
1841: PetscErrorCode PetscLogClassGetClassId(const char name[], PetscClassId *classid)
1842: {
1843:   PetscLogClass     log_class;
1844:   PetscLogClassInfo class_info;
1845:   PetscLogState     state;

1847:   PetscFunctionBegin;
1848:   *classid = -1;
1849:   PetscCall(PetscLogGetState(&state));
1850:   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
1851:   PetscCall(PetscLogStateGetClassFromName(state, name, &log_class));
1852:   if (log_class < 0) {
1853:     *classid = -1;
1854:     PetscFunctionReturn(PETSC_SUCCESS);
1855:   }
1856:   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
1857:   *classid = class_info.classid;
1858:   PetscFunctionReturn(PETSC_SUCCESS);
1859: }

1861: /*@C
1862:   PetscLogClassIdGetName - Returns a `PetscClassId`'s name.

1864:   Not Collective

1866:   Input Parameter:
1867: . classid - A `PetscClassId`

1869:   Output Parameter:
1870: . name - The class name

1872:   Level: intermediate

1874: .seealso: [](ch_profiling), `PetscLogClassRegister()`, `PetscLogClassBegin()`, `PetscLogClassEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadClass()`
1875: @*/
1876: PetscErrorCode PetscLogClassIdGetName(PetscClassId classid, const char **name)
1877: {
1878:   PetscLogClass     log_class;
1879:   PetscLogClassInfo class_info;
1880:   PetscLogState     state;

1882:   PetscFunctionBegin;
1883:   PetscCall(PetscLogGetState(&state));
1884:   PetscCall(PetscLogStateGetClassFromClassId(state, classid, &log_class));
1885:   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
1886:   *name = class_info.name;
1887:   PetscFunctionReturn(PETSC_SUCCESS);
1888: }

1890: /*------------------------------------------------ Output Functions -------------------------------------------------*/
1891: /*@
1892:   PetscLogDump - Dumps logs of objects to a file. This file is intended to
1893:   be read by bin/petscview. This program no longer exists.

1895:   Collective on `PETSC_COMM_WORLD`

1897:   Input Parameter:
1898: . sname - an optional file name

1900:   Example Usage:
1901: .vb
1902:   PetscInitialize(...);
1903:   PetscLogDefaultBegin();
1904:   // ... code ...
1905:   PetscLogDump(filename);
1906:   PetscFinalize();
1907: .ve

1909:   Level: advanced

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

1915: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
1916: @*/
1917: PetscErrorCode PetscLogDump(const char sname[])
1918: {
1919:   PetscLogHandler handler;

1921:   PetscFunctionBegin;
1922:   PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1923:   PetscCall(PetscLogHandlerDump(handler, sname));
1924:   PetscFunctionReturn(PETSC_SUCCESS);
1925: }

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

1930:   Collective on `PETSC_COMM_WORLD`

1932:   Input Parameter:
1933: . sname - filename for the MPE logfile

1935:   Level: advanced

1937: .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogMPEBegin()`
1938: @*/
1939: PetscErrorCode PetscLogMPEDump(const char sname[])
1940: {
1941:   PetscFunctionBegin;
1942:   #if defined(PETSC_HAVE_MPE)
1943:   if (PetscBeganMPE) {
1944:     char name[PETSC_MAX_PATH_LEN];

1946:     PetscCall(PetscInfo(0, "Finalizing MPE.\n"));
1947:     if (sname) {
1948:       PetscCall(PetscStrncpy(name, sname, sizeof(name)));
1949:     } else {
1950:       PetscCall(PetscGetProgramName(name, sizeof(name)));
1951:     }
1952:     PetscCall(MPE_Finish_log(name));
1953:   } else {
1954:     PetscCall(PetscInfo(0, "Not finalizing MPE (not started by PETSc).\n"));
1955:   }
1956:   #else
1957:   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
1958:   #endif
1959:   PetscFunctionReturn(PETSC_SUCCESS);
1960: }

1962: /*@
1963:   PetscLogView - Prints a summary of the logging.

1965:   Collective

1967:   Input Parameter:
1968: . viewer - an ASCII viewer

1970:   Options Database Keys:
1971: + -log_view [:filename]                    - Prints summary of log information
1972: . -log_view :filename.py:ascii_info_detail - Saves logging information from each process as a Python file
1973: . -log_view :filename.xml:ascii_xml        - Saves a summary of the logging information in a nested format (see below for how to view it)
1974: . -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)
1975: . -log_view_memory                         - Also display memory usage in each event
1976: . -log_view_gpu_time                       - Also display time in each event for GPU kernels (Note this may slow the computation)
1977: . -log_all                                 - Saves a file Log.rank for each MPI rank with details of each step of the computation
1978: - -log_trace [filename]                    - Displays a trace of what each process is doing

1980:   Level: beginner

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

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

1988:   If PETSc is configured with --with-logging=0 then this functionality is not available

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

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

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

2008: .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogDump()`
2009: @*/
2010: PetscErrorCode PetscLogView(PetscViewer viewer)
2011: {
2012:   PetscBool         isascii;
2013:   PetscViewerFormat format;
2014:   int               stage;
2015:   PetscLogState     state;
2016:   PetscIntStack     temp_stack;
2017:   PetscLogHandler   handler;
2018:   PetscBool         is_empty;

2020:   PetscFunctionBegin;
2021:   PetscCall(PetscLogGetState(&state));
2022:   /* Pop off any stages the user forgot to remove */
2023:   PetscCall(PetscIntStackCreate(&temp_stack));
2024:   PetscCall(PetscLogStateGetCurrentStage(state, &stage));
2025:   while (stage >= 0) {
2026:     PetscCall(PetscLogStagePop());
2027:     PetscCall(PetscIntStackPush(temp_stack, stage));
2028:     PetscCall(PetscLogStateGetCurrentStage(state, &stage));
2029:   }
2030:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2031:   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Currently can only view logging to ASCII");
2032:   PetscCall(PetscViewerGetFormat(viewer, &format));
2033:   if (format == PETSC_VIEWER_ASCII_XML || format == PETSC_VIEWER_ASCII_FLAMEGRAPH) {
2034:     PetscCall(PetscLogGetHandler(PETSCLOGHANDLERNESTED, &handler));
2035:     PetscCall(PetscLogHandlerView(handler, viewer));
2036:   } else {
2037:     PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
2038:     PetscCall(PetscLogHandlerView(handler, viewer));
2039:   }
2040:   PetscCall(PetscIntStackEmpty(temp_stack, &is_empty));
2041:   while (!is_empty) {
2042:     PetscCall(PetscIntStackPop(temp_stack, &stage));
2043:     PetscCall(PetscLogStagePush(stage));
2044:     PetscCall(PetscIntStackEmpty(temp_stack, &is_empty));
2045:   }
2046:   PetscCall(PetscIntStackDestroy(temp_stack));
2047:   PetscFunctionReturn(PETSC_SUCCESS);
2048: }

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

2053:   Collective on `PETSC_COMM_WORLD`

2055:   Level: developer

2057: .seealso: [](ch_profiling), `PetscLogView()`
2058: @*/
2059: PetscErrorCode PetscLogViewFromOptions(void)
2060: {
2061:   PetscInt          n_max = PETSC_LOG_VIEW_FROM_OPTIONS_MAX;
2062:   PetscViewer       viewers[PETSC_LOG_VIEW_FROM_OPTIONS_MAX];
2063:   PetscViewerFormat formats[PETSC_LOG_VIEW_FROM_OPTIONS_MAX];
2064:   PetscBool         flg;

2066:   PetscFunctionBegin;
2067:   PetscCall(PetscOptionsCreateViewers(PETSC_COMM_WORLD, NULL, NULL, "-log_view", &n_max, viewers, formats, &flg));
2068:   for (PetscInt i = 0; i < n_max; i++) {
2069:     PetscCall(PetscViewerPushFormat(viewers[i], formats[i]));
2070:     PetscCall(PetscLogView(viewers[i]));
2071:     PetscCall(PetscViewerPopFormat(viewers[i]));
2072:     PetscCall(PetscViewerDestroy(&viewers[i]));
2073:   }
2074:   PetscFunctionReturn(PETSC_SUCCESS);
2075: }

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

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

2083:   Logically Collective on `PETSC_COMM_WORLD`

2085:   Input Parameter:
2086: . newThresh - the threshold to use

2088:   Output Parameter:
2089: . oldThresh - the previously set threshold value

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

2094:   Example Usage:
2095: .vb
2096:   PetscInitialize(...);
2097:   PetscLogNestedBegin();
2098:   PetscLogSetThreshold(0.1,&oldthresh);
2099:   // ... code ...
2100:   PetscLogView(viewer);
2101:   PetscFinalize();
2102: .ve

2104:   Level: advanced

2106:   Note:
2107:   This threshold is only used by the nested log handler

2109: .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`,
2110:           `PetscLogNestedBegin()`
2111: @*/
2112: PetscErrorCode PetscLogSetThreshold(PetscLogDouble newThresh, PetscLogDouble *oldThresh)
2113: {
2114:   PetscLogHandler handler;

2116:   PetscFunctionBegin;
2117:   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERNESTED, &handler));
2118:   PetscCall(PetscLogHandlerNestedSetThreshold(handler, newThresh, oldThresh));
2119:   PetscFunctionReturn(PETSC_SUCCESS);
2120: }

2122: /*----------------------------------------------- Counter Functions -------------------------------------------------*/
2123: /*@
2124:   PetscGetFlops - Returns the number of flops used on this processor
2125:   since the program began.

2127:   Not Collective

2129:   Output Parameter:
2130: . flops - number of floating point operations

2132:   Level: intermediate

2134:   Notes:
2135:   A global counter logs all PETSc flop counts.  The user can use
2136:   `PetscLogFlops()` to increment this counter to include flops for the
2137:   application code.

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

2141: .seealso: [](ch_profiling), `PetscLogGpuFlops()`, `PetscTime()`, `PetscLogFlops()`
2142: @*/
2143: PetscErrorCode PetscGetFlops(PetscLogDouble *flops)
2144: {
2145:   PetscFunctionBegin;
2146:   *flops = petsc_TotalFlops;
2147:   PetscFunctionReturn(PETSC_SUCCESS);
2148: }

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

2153:   Not Collective

2155:   Input Parameters:
2156: + obj    - the `PetscObject`
2157: . format - a printf-style format string
2158: - ...    - printf arguments to format

2160:   Level: developer

2162: .seealso: [](ch_profiling), `PetscLogObjectCreate()`, `PetscLogObjectDestroy()`, `PetscLogGetDefaultHandler()`
2163: @*/
2164: PetscErrorCode PetscLogObjectState(PetscObject obj, const char format[], ...)
2165: {
2166:   PetscFunctionBegin;
2167:   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
2168:     PetscLogHandler h = PetscLogHandlers[i].handler;

2170:     if (h) {
2171:       va_list Argp;
2172:       va_start(Argp, format);
2173:       PetscCall(PetscLogHandlerLogObjectState_Internal(h, obj, format, Argp));
2174:       va_end(Argp);
2175:     }
2176:   }
2177:   PetscFunctionReturn(PETSC_SUCCESS);
2178: }

2180: /*MC
2181:   PetscLogFlops - Adds floating point operations to the global counter.

2183:   Synopsis:
2184: #include <petsclog.h>
2185:   PetscErrorCode PetscLogFlops(PetscLogDouble f)

2187:   Not Collective

2189:   Input Parameter:
2190: . f - flop counter

2192:   Example Usage:
2193: .vb
2194:   PetscLogEvent USER_EVENT;

2196:   PetscLogEventRegister("User event", 0, &USER_EVENT);
2197:   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
2198:   [code segment to monitor]
2199:   PetscLogFlops(user_flops)
2200:   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
2201: .ve

2203:   Level: intermediate

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

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

2212: /*MC
2213:   PetscPreLoadBegin - Begin a segment of code that may be preloaded (run twice) to get accurate
2214:   timings

2216:   Synopsis:
2217: #include <petsclog.h>
2218:   void PetscPreLoadBegin(PetscBool flag, char *name);

2220:   Not Collective

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

2227:   Example Usage:
2228: .vb
2229:   PetscPreLoadBegin(PETSC_TRUE, "first stage");
2230:   // lines of code
2231:   PetscPreLoadStage("second stage");
2232:   // lines of code
2233:   PetscPreLoadEnd();
2234: .ve

2236:   Level: intermediate

2238:   Note:
2239:   Only works in C/C++, not Fortran

2241:   Flags available within the macro\:
2242: + PetscPreLoadingUsed - `PETSC_TRUE` if we are or have done preloading
2243: . PetscPreLoadingOn   - `PETSC_TRUE` if it is CURRENTLY doing preload
2244: . PetscPreLoadIt      - `0` for the first computation (with preloading turned off it is only
2245:                         `0`) `1`  for the second
2246: - PetscPreLoadMax     - number of times it will do the computation, only one when preloading is
2247:                         turned on

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

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

2255: /*MC
2256:   PetscPreLoadEnd - End a segment of code that may be preloaded (run twice) to get accurate
2257:   timings

2259:   Synopsis:
2260: #include <petsclog.h>
2261:   void PetscPreLoadEnd(void);

2263:   Not Collective

2265:   Example Usage:
2266: .vb
2267:   PetscPreLoadBegin(PETSC_TRUE, "first stage");
2268:   // lines of code
2269:   PetscPreLoadStage("second stage");
2270:   // lines of code
2271:   PetscPreLoadEnd();
2272: .ve

2274:   Level: intermediate

2276:   Note:
2277:   Only works in C/C++ not Fortran

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

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

2285:   Synopsis:
2286: #include <petsclog.h>
2287:   void PetscPreLoadStage(char *name);

2289:   Not Collective

2291:   Example Usage:
2292: .vb
2293:   PetscPreLoadBegin(PETSC_TRUE,"first stage");
2294:   // lines of code
2295:   PetscPreLoadStage("second stage");
2296:   // lines of code
2297:   PetscPreLoadEnd();
2298: .ve

2300:   Level: intermediate

2302:   Note:
2303:   Only works in C/C++ not Fortran

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

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

2311: /*@
2312:   PetscLogGpuTime - turn on the logging of GPU time for GPU kernels

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

2317:   Level: advanced

2319:   Notes:
2320:   Turning on the timing of the GPU kernels can slow down the entire computation and should only
2321:   be used when studying the performance of individual operations on GPU such as vector operations and
2322:   matrix-vector operations.

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

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

2329: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTimeBegin()`
2330: @*/
2331: PetscErrorCode PetscLogGpuTime(void)
2332: {
2333:   PetscFunctionBegin;
2334:   PetscCheck(petsc_gtime == 0.0, PETSC_COMM_SELF, PETSC_ERR_SUP, "GPU logging has already been turned on");
2335:   PetscLogGpuTimeFlag = PETSC_TRUE;
2336:   PetscFunctionReturn(PETSC_SUCCESS);
2337: }

2339: /*@
2340:   PetscLogGpuTimeBegin - Start timer for device

2342:   Level: intermediate

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

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

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

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

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

2361:   Developer Notes:
2362:   The GPU event timer captures the execution time of all the kernels launched in the default
2363:   stream by the CPU between `PetscLogGpuTimeBegin()` and `PetsLogGpuTimeEnd()`.

2365:   `PetscLogGpuTimeBegin()` and `PetsLogGpuTimeEnd()` insert the begin and end events into the
2366:   default stream (stream 0). The device will record a time stamp for the event when it reaches
2367:   that event in the stream. The function xxxEventSynchronize() is called in
2368:   `PetsLogGpuTimeEnd()` to block CPU execution, but not continued GPU execution, until the
2369:   timer event is recorded.

2371: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTime()`
2372: @*/
2373: PetscErrorCode PetscLogGpuTimeBegin(void)
2374: {
2375:   PetscBool isActive;

2377:   PetscFunctionBegin;
2378:   PetscCall(PetscLogEventBeginIsActive(&isActive));
2379:   if (!isActive || !PetscLogGpuTimeFlag) PetscFunctionReturn(PETSC_SUCCESS);
2380:     #if defined(PETSC_HAVE_DEVICE) && !defined(PETSC_HAVE_KOKKOS_WITHOUT_GPU)
2381:   {
2382:     PetscDeviceContext dctx;

2384:     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2385:     PetscCall(PetscDeviceContextBeginTimer_Internal(dctx));
2386:   }
2387:     #else
2388:   PetscCall(PetscTimeSubtract(&petsc_gtime));
2389:     #endif
2390:   PetscFunctionReturn(PETSC_SUCCESS);
2391: }

2393: /*@
2394:   PetscLogGpuTimeEnd - Stop timer for device

2396:   Level: intermediate

2398: .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeBegin()`
2399: @*/
2400: PetscErrorCode PetscLogGpuTimeEnd(void)
2401: {
2402:   PetscBool isActive;

2404:   PetscFunctionBegin;
2405:   PetscCall(PetscLogEventEndIsActive(&isActive));
2406:   if (!isActive || !PetscLogGpuTimeFlag) PetscFunctionReturn(PETSC_SUCCESS);
2407:     #if defined(PETSC_HAVE_DEVICE) && !defined(PETSC_HAVE_KOKKOS_WITHOUT_GPU)
2408:   {
2409:     PetscDeviceContext dctx;
2410:     PetscLogDouble     elapsed;

2412:     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2413:     PetscCall(PetscDeviceContextEndTimer_Internal(dctx, &elapsed));
2414:     petsc_gtime += (elapsed / 1000.0);
2415:   }
2416:     #else
2417:   PetscCall(PetscTimeAdd(&petsc_gtime));
2418:     #endif
2419:   PetscFunctionReturn(PETSC_SUCCESS);
2420: }

2422:   #endif /* end of PETSC_HAVE_DEVICE */

2424: #endif /* PETSC_USE_LOG*/

2426: /* -- Utility functions for logging from Fortran -- */

2428: PETSC_EXTERN PetscErrorCode PetscASend(int count, int datatype)
2429: {
2430:   PetscFunctionBegin;
2431: #if PetscDefined(USE_LOG)
2432:   PetscCall(PetscAddLogDouble(&petsc_send_ct, &petsc_send_ct_th, 1));
2433:   #if !defined(MPIUNI_H) && !defined(PETSC_HAVE_BROKEN_RECURSIVE_MACRO)
2434:   PetscCall(PetscMPITypeSize(count, MPI_Type_f2c((MPI_Fint)datatype), &petsc_send_len, &petsc_send_len_th));
2435:   #endif
2436: #endif
2437:   PetscFunctionReturn(PETSC_SUCCESS);
2438: }

2440: PETSC_EXTERN PetscErrorCode PetscARecv(int count, int datatype)
2441: {
2442:   PetscFunctionBegin;
2443: #if PetscDefined(USE_LOG)
2444:   PetscCall(PetscAddLogDouble(&petsc_recv_ct, &petsc_recv_ct_th, 1));
2445:   #if !defined(MPIUNI_H) && !defined(PETSC_HAVE_BROKEN_RECURSIVE_MACRO)
2446:   PetscCall(PetscMPITypeSize(count, MPI_Type_f2c((MPI_Fint)datatype), &petsc_recv_len, &petsc_recv_len_th));
2447:   #endif
2448: #endif
2449:   PetscFunctionReturn(PETSC_SUCCESS);
2450: }

2452: PETSC_EXTERN PetscErrorCode PetscAReduce(void)
2453: {
2454:   PetscFunctionBegin;
2455:   if (PetscDefined(USE_LOG)) PetscCall(PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, 1));
2456:   PetscFunctionReturn(PETSC_SUCCESS);
2457: }

2459: PetscClassId PETSC_LARGEST_CLASSID = PETSC_SMALLEST_CLASSID;
2460: PetscClassId PETSC_OBJECT_CLASSID  = 0;

2462: static PetscBool PetscLogInitializeCalled = PETSC_FALSE;

2464: PETSC_INTERN PetscErrorCode PetscLogInitialize(void)
2465: {
2466:   int stage;

2468:   PetscFunctionBegin;
2469:   if (PetscLogInitializeCalled) PetscFunctionReturn(PETSC_SUCCESS);
2470:   PetscLogInitializeCalled = PETSC_TRUE;
2471:   if (PetscDefined(USE_LOG)) {
2472:     /* Setup default logging structures */
2473:     PetscCall(PetscLogStateCreate(&petsc_log_state));
2474:     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
2475:       if (PetscLogHandlers[i].handler) PetscCall(PetscLogHandlerSetState(PetscLogHandlers[i].handler, petsc_log_state));
2476:     }
2477:     PetscCall(PetscLogStateStageRegister(petsc_log_state, "Main Stage", &stage));
2478:     PetscCall(PetscSpinlockCreate(&PetscLogSpinLock));
2479: #if defined(PETSC_HAVE_THREADSAFETY)
2480:     petsc_log_tid = 0;
2481:     petsc_log_gid = 0;
2482: #endif

2484:     /* All processors sync here for more consistent logging */
2485:     PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
2486:     PetscCall(PetscTime(&petsc_BaseTime));
2487:     PetscCall(PetscLogStagePush(stage));
2488:   }
2489:   PetscFunctionReturn(PETSC_SUCCESS);
2490: }

2492: PETSC_INTERN PetscErrorCode PetscLogFinalize(void)
2493: {
2494:   PetscFunctionBegin;
2495:   if (PetscDefined(USE_LOG)) {
2496:     /* Resetting phase */
2497:     // pop remaining stages
2498:     if (petsc_log_state) {
2499:       while (petsc_log_state->current_stage >= 0) { PetscCall(PetscLogStagePop()); }
2500:     }
2501:     for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) PetscCall(PetscLogHandlerDestroy(&PetscLogHandlers[i].handler));
2502:     PetscCall(PetscArrayzero(PetscLogHandlers, PETSC_LOG_HANDLER_MAX));
2503:     PetscCall(PetscLogStateDestroy(&petsc_log_state));

2505:     petsc_TotalFlops         = 0.0;
2506:     petsc_BaseTime           = 0.0;
2507:     petsc_TotalFlops         = 0.0;
2508:     petsc_send_ct            = 0.0;
2509:     petsc_recv_ct            = 0.0;
2510:     petsc_send_len           = 0.0;
2511:     petsc_recv_len           = 0.0;
2512:     petsc_isend_ct           = 0.0;
2513:     petsc_irecv_ct           = 0.0;
2514:     petsc_isend_len          = 0.0;
2515:     petsc_irecv_len          = 0.0;
2516:     petsc_wait_ct            = 0.0;
2517:     petsc_wait_any_ct        = 0.0;
2518:     petsc_wait_all_ct        = 0.0;
2519:     petsc_sum_of_waits_ct    = 0.0;
2520:     petsc_allreduce_ct       = 0.0;
2521:     petsc_gather_ct          = 0.0;
2522:     petsc_scatter_ct         = 0.0;
2523:     petsc_TotalFlops_th      = 0.0;
2524:     petsc_send_ct_th         = 0.0;
2525:     petsc_recv_ct_th         = 0.0;
2526:     petsc_send_len_th        = 0.0;
2527:     petsc_recv_len_th        = 0.0;
2528:     petsc_isend_ct_th        = 0.0;
2529:     petsc_irecv_ct_th        = 0.0;
2530:     petsc_isend_len_th       = 0.0;
2531:     petsc_irecv_len_th       = 0.0;
2532:     petsc_wait_ct_th         = 0.0;
2533:     petsc_wait_any_ct_th     = 0.0;
2534:     petsc_wait_all_ct_th     = 0.0;
2535:     petsc_sum_of_waits_ct_th = 0.0;
2536:     petsc_allreduce_ct_th    = 0.0;
2537:     petsc_gather_ct_th       = 0.0;
2538:     petsc_scatter_ct_th      = 0.0;

2540:     petsc_ctog_ct    = 0.0;
2541:     petsc_gtoc_ct    = 0.0;
2542:     petsc_ctog_sz    = 0.0;
2543:     petsc_gtoc_sz    = 0.0;
2544:     petsc_gflops     = 0.0;
2545:     petsc_gtime      = 0.0;
2546:     petsc_ctog_ct_th = 0.0;
2547:     petsc_gtoc_ct_th = 0.0;
2548:     petsc_ctog_sz_th = 0.0;
2549:     petsc_gtoc_sz_th = 0.0;
2550:     petsc_gflops_th  = 0.0;
2551:     petsc_gtime_th   = 0.0;
2552:   }
2553:   PETSC_LARGEST_CLASSID    = PETSC_SMALLEST_CLASSID;
2554:   PETSC_OBJECT_CLASSID     = 0;
2555:   PetscLogInitializeCalled = PETSC_FALSE;
2556:   PetscFunctionReturn(PETSC_SUCCESS);
2557: }

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

2562:   Not Collective

2564:   Input Parameter:
2565: . name - The class name

2567:   Output Parameter:
2568: . oclass - The class id or classid

2570:   Level: developer

2572: .seealso: [](ch_profiling), `PetscLogEventRegister()`
2573: @*/
2574: PetscErrorCode PetscClassIdRegister(const char name[], PetscClassId *oclass)
2575: {
2576:   PetscFunctionBegin;
2577:   *oclass = ++PETSC_LARGEST_CLASSID;
2578: #if defined(PETSC_USE_LOG)
2579:   {
2580:     PetscLogState state;
2581:     PetscLogClass logclass;

2583:     PetscCall(PetscLogGetState(&state));
2584:     if (state) PetscCall(PetscLogStateClassRegister(state, name, *oclass, &logclass));
2585:   }
2586: #endif
2587:   PetscFunctionReturn(PETSC_SUCCESS);
2588: }