xref: /petsc/src/sys/logging/plog.c (revision 0d5ef98addb54ced821e7e5fade9ccac0ec8ccde)
1 /*
2       PETSc code to log object creation and destruction and PETSc events.
3 
4       This provides the public API used by the rest of PETSc and by users.
5 
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.
8 
9       ***
10 
11       This file, and only this file, is for functions that interact with the global logging state
12 */
13 #include <petsc/private/logimpl.h> /*I    "petscsys.h"   I*/
14 #include <petsc/private/loghandlerimpl.h>
15 #include <petsctime.h>
16 #include <petscviewer.h>
17 #include <petscdevice.h>
18 #include <petsc/private/deviceimpl.h>
19 
20 #if defined(PETSC_HAVE_THREADSAFETY)
21 
22 PetscInt           petsc_log_gid = -1; /* Global threadId counter */
23 PETSC_TLS PetscInt petsc_log_tid = -1; /* Local threadId */
24 
25 /* shared variables */
26 PetscSpinlock PetscLogSpinLock;
27 
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 }
37 
38 #endif
39 
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 */
58 
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;
76 
77 PetscLogDouble petsc_ctog_ct        = 0.0; /* The total number of CPU to GPU copies */
78 PetscLogDouble petsc_gtoc_ct        = 0.0; /* The total number of GPU to CPU copies */
79 PetscLogDouble petsc_ctog_sz        = 0.0; /* The total size of CPU to GPU copies */
80 PetscLogDouble petsc_gtoc_sz        = 0.0; /* The total size of GPU to CPU copies */
81 PetscLogDouble petsc_ctog_ct_scalar = 0.0; /* The total number of CPU to GPU copies */
82 PetscLogDouble petsc_gtoc_ct_scalar = 0.0; /* The total number of GPU to CPU copies */
83 PetscLogDouble petsc_ctog_sz_scalar = 0.0; /* The total size of CPU to GPU copies */
84 PetscLogDouble petsc_gtoc_sz_scalar = 0.0; /* The total size of GPU to CPU copies */
85 PetscLogDouble petsc_gflops         = 0.0; /* The flops done on a GPU */
86 PetscLogDouble petsc_gtime          = 0.0; /* The time spent on a GPU */
87 
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;
98 
99 PetscBool PetscLogMemory = PETSC_FALSE;
100 PetscBool PetscLogSyncOn = PETSC_FALSE;
101 
102 PetscBool PetscLogGpuTimeFlag = PETSC_FALSE;
103 
104 PetscLogState petsc_log_state = NULL;
105 
106 #define PETSC_LOG_HANDLER_HOT_BLANK {NULL, NULL, NULL, NULL, NULL, NULL}
107 
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 };
114 
115 #undef PETSC_LOG_HANDLERS_HOT_BLANK
116 
117 #if defined(PETSC_USE_LOG)
118   #include <../src/sys/logging/handler/impls/default/logdefault.h>
119 
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 }
129 
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 }
140 
141   #endif
142 
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;
152 
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 }
162 
163 /*@
164   PetscLogGetDefaultHandler - Get the default log handler if it is running.
165 
166   Not collective
167 
168   Output Parameter:
169 . handler - the default `PetscLogHandler`, or `NULL` if it is not running.
170 
171   Level: developer
172 
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`.
177 
178 .seealso: [](ch_profiling)
179 @*/
180 PetscErrorCode PetscLogGetDefaultHandler(PetscLogHandler *handler)
181 {
182   PetscFunctionBegin;
183   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, handler));
184   PetscFunctionReturn(PETSC_SUCCESS);
185 }
186 
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 }
195 
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()`).
201 
202   Collective on `PETSC_COMM_WORLD`
203 
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
208 
209   Level: developer
210 
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 }
220 
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 }
232 
233 /*@
234   PetscLogHandlerStart - Connect a log handler to PETSc's global logging stream and state.
235 
236   Logically collective
237 
238   Input Parameters:
239 . h - a `PetscLogHandler`
240 
241   Level: developer
242 
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.
247 
248   There is a limit of `PESC_LOG_HANDLER_MAX` handlers that can be active at one time.
249 
250   To disconnect a handler from the global stream call `PetscLogHandlerStop()`.
251 
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.
256 
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;
272 
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 }
294 
295 /*@
296   PetscLogHandlerStop - Disconnect a log handler from PETSc's global logging stream.
297 
298   Logically collective
299 
300   Input Parameters:
301 . h - a `PetscLogHandler`
302 
303   Level: developer
304 
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()`),
309 
310   When a log handler is stopped, the remaining stages will be popped before it is
311   disconnected from the log stream.
312 
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;
324 
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];
333 
334           PetscCall(PetscIntStackPush(temp_stack, stage));
335         }
336         for (int s = 0; s < stack_height; s++) {
337           PetscLogStage stage;
338           PetscBool     empty;
339 
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 }
357 
358 /*@
359   PetscLogIsActive - Check if logging is currently in progress.
360 
361   Not Collective
362 
363   Output Parameter:
364 . isActive - `PETSC_TRUE` if logging is in progress, `PETSC_FALSE` otherwise
365 
366   Level: beginner
367 
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 }
384 
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 }
399 
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 }
414 
415 PETSC_INTERN PetscErrorCode PetscLogTypeBegin(PetscLogHandlerType type)
416 {
417   PetscLogHandler handler;
418 
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 }
428 
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.
433 
434   Logically Collective on `PETSC_COMM_WORLD`
435 
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))
439 
440   Example Usage:
441 .vb
442       PetscInitialize(...);
443       PetscLogDefaultBegin();
444        ... code ...
445       PetscLogView(viewer); or PetscLogDump();
446       PetscFinalize();
447 .ve
448 
449   Level: advanced
450 
451   Note:
452   `PetscLogView()` or `PetscLogDump()` actually cause the printing of
453   the logging information.
454 
455 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`
456 @*/
457 PetscErrorCode PetscLogDefaultBegin(void)
458 {
459   PetscFunctionBegin;
460   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERDEFAULT));
461   PetscFunctionReturn(PETSC_SUCCESS);
462 }
463 
464 /*@C
465   PetscLogTraceBegin - Begins trace logging.  Every time a PETSc event
466   begins or ends, the event name is printed.
467 
468   Logically Collective on `PETSC_COMM_WORLD`, No Fortran Support
469 
470   Input Parameter:
471 . file - The file to print trace in (e.g. stdout)
472 
473   Options Database Key:
474 . -log_trace [filename] - Begins `PetscLogTraceBegin()`
475 
476   Level: intermediate
477 
478   Notes:
479   `PetscLogTraceBegin()` prints the processor number, the execution time (sec),
480   then "Event begin:" or "Event end:" followed by the event name.
481 
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.
485 
486 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogDefaultBegin()`
487 @*/
488 PetscErrorCode PetscLogTraceBegin(FILE *file)
489 {
490   PetscLogHandler handler;
491 
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 }
500 
501 PETSC_INTERN PetscErrorCode PetscLogHandlerCreate_Nested(MPI_Comm, PetscLogHandler *);
502 
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.
506 
507   Logically Collective on `PETSC_COMM_WORLD`, No Fortran Support
508 
509   Options Database Keys:
510 . -log_view :filename.xml:ascii_xml - Prints an XML summary of flop and timing information to the file
511 
512   Example Usage:
513 .vb
514       PetscInitialize(...);
515       PetscLogNestedBegin();
516        ... code ...
517       PetscLogView(viewer);
518       PetscFinalize();
519 .ve
520 
521   Level: advanced
522 
523 .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`
524 @*/
525 PetscErrorCode PetscLogNestedBegin(void)
526 {
527   PetscFunctionBegin;
528   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERNESTED));
529   PetscFunctionReturn(PETSC_SUCCESS);
530 }
531 
532 /*@C
533   PetscLogLegacyCallbacksBegin - Create and start a log handler from callbacks
534   matching the now deprecated function pointers `PetscLogPLB`, `PetscLogPLE`,
535   `PetscLogPHC`, `PetscLogPHD`.
536 
537   Logically Collective on `PETSC_COMM_WORLD`
538 
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`)
544 
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`)
552 
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`)
560 
561   Calling sequence of `PetscLogPHC`:
562 . o - a `PetscObject` that has just been created
563 
564   Calling sequence of `PetscLogPHD`:
565 . o - a `PetscObject` that is about to be destroyed
566 
567   Level: advanced
568 
569   Notes:
570   This is for transitioning from the deprecated function `PetscLogSet()` and should not be used in new code.
571 
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.
575 
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;
581 
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 }
588 
589   #if defined(PETSC_HAVE_MPE)
590     #include <mpe.h>
591 static PetscBool PetscBeganMPE = PETSC_FALSE;
592   #endif
593 
594 /*@C
595   PetscLogMPEBegin - Turns on MPE logging of events. This creates large log files and slows the
596   program down.
597 
598   Collective on `PETSC_COMM_WORLD`, No Fortran Support
599 
600   Options Database Key:
601 . -log_mpe - Prints extensive log information
602 
603   Level: advanced
604 
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).
609 
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());
621 
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 }
632 
633   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
634     #include <../src/sys/perfstubs/timer.h>
635   #endif
636 
637 /*@C
638   PetscLogPerfstubsBegin - Turns on logging of events using the perfstubs interface.
639 
640   Collective on `PETSC_COMM_WORLD`, No Fortran Support
641 
642   Options Database Key:
643 . -log_perfstubs - use an external log handler through the perfstubs interface
644 
645   Level: advanced
646 
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 }
659 
660 /*@
661   PetscLogActions - Determines whether actions are logged for the default log handler.
662 
663   Not Collective
664 
665   Input Parameter:
666 . flag - `PETSC_TRUE` if actions are to be logged
667 
668   Options Database Key:
669 + -log_exclude_actions - (deprecated) Does nothing
670 - -log_include_actions - Turn on action logging
671 
672   Level: intermediate
673 
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.
677 
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;
685 
686     if (h) PetscCall(PetscLogHandlerSetLogActions(h, flag));
687   }
688   PetscFunctionReturn(PETSC_SUCCESS);
689 }
690 
691 /*@
692   PetscLogObjects - Determines whether objects are logged for the graphical viewer.
693 
694   Not Collective
695 
696   Input Parameter:
697 . flag - `PETSC_TRUE` if objects are to be logged
698 
699   Options Database Key:
700 + -log_exclude_objects - (deprecated) Does nothing
701 - -log_include_objects - Turns on object logging
702 
703   Level: intermediate
704 
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.
708 
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;
716 
717     if (h) PetscCall(PetscLogHandlerSetLogObjects(h, flag));
718   }
719   PetscFunctionReturn(PETSC_SUCCESS);
720 }
721 
722 /*------------------------------------------------ Stage Functions --------------------------------------------------*/
723 /*@
724   PetscLogStageRegister - Attaches a character string name to a logging stage.
725 
726   Not Collective
727 
728   Input Parameter:
729 . sname - The name to associate with that stage
730 
731   Output Parameter:
732 . stage - The stage number or -1 if logging is not active (`PetscLogIsActive()`).
733 
734   Level: intermediate
735 
736 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`
737 @*/
738 PetscErrorCode PetscLogStageRegister(const char sname[], PetscLogStage *stage)
739 {
740   PetscLogState state;
741 
742   PetscFunctionBegin;
743   *stage = -1;
744   PetscCall(PetscLogGetState(&state));
745   if (state) PetscCall(PetscLogStateStageRegister(state, sname, stage));
746   PetscFunctionReturn(PETSC_SUCCESS);
747 }
748 
749 /*@
750   PetscLogStagePush - This function pushes a stage on the logging stack. Events started and stopped until `PetscLogStagePop()` will be associated with the stage
751 
752   Not Collective
753 
754   Input Parameter:
755 . stage - The stage on which to log
756 
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
771 
772   Level: intermediate
773 
774   Note:
775   Use `PetscLogStageRegister()` to register a stage.
776 
777 .seealso: [](ch_profiling), `PetscLogStagePop()`, `PetscLogStageRegister()`, `PetscBarrier()`
778 @*/
779 PetscErrorCode PetscLogStagePush(PetscLogStage stage)
780 {
781   PetscLogState state;
782 
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 }
793 
794 /*@
795   PetscLogStagePop - This function pops a stage from the logging stack that was pushed with `PetscLogStagePush()`
796 
797   Not Collective
798 
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
813 
814   Level: intermediate
815 
816 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStageRegister()`, `PetscBarrier()`
817 @*/
818 PetscErrorCode PetscLogStagePop(void)
819 {
820   PetscLogState state;
821   PetscLogStage current_stage;
822 
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 }
834 
835 /*@
836   PetscLogStageSetActive - Sets if a stage is used for `PetscLogEventBegin()` and `PetscLogEventEnd()`.
837 
838   Not Collective
839 
840   Input Parameters:
841 + stage    - The stage
842 - isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
843 
844   Level: intermediate
845 
846   Note:
847   If this is set to `PETSC_FALSE` the logging acts as if the stage did not exist
848 
849 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
850 @*/
851 PetscErrorCode PetscLogStageSetActive(PetscLogStage stage, PetscBool isActive)
852 {
853   PetscLogState state;
854 
855   PetscFunctionBegin;
856   PetscCall(PetscLogGetState(&state));
857   if (state) PetscCall(PetscLogStateStageSetActive(state, stage, isActive));
858   PetscFunctionReturn(PETSC_SUCCESS);
859 }
860 
861 /*@
862   PetscLogStageGetActive - Checks if a stage is used for `PetscLogEventBegin()` and `PetscLogEventEnd()`.
863 
864   Not Collective
865 
866   Input Parameter:
867 . stage - The stage
868 
869   Output Parameter:
870 . isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
871 
872   Level: intermediate
873 
874 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
875 @*/
876 PetscErrorCode PetscLogStageGetActive(PetscLogStage stage, PetscBool *isActive)
877 {
878   PetscLogState state;
879 
880   PetscFunctionBegin;
881   *isActive = PETSC_FALSE;
882   PetscCall(PetscLogGetState(&state));
883   if (state) PetscCall(PetscLogStateStageGetActive(state, stage, isActive));
884   PetscFunctionReturn(PETSC_SUCCESS);
885 }
886 
887 /*@
888   PetscLogStageSetVisible - Determines stage visibility in `PetscLogView()`
889 
890   Not Collective
891 
892   Input Parameters:
893 + stage     - The stage
894 - isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
895 
896   Level: intermediate
897 
898   Developer Notes:
899   Visibility only affects the default log handler in `PetscLogView()`: stages that are
900   set to invisible are suppressed from output.
901 
902 .seealso: [](ch_profiling), `PetscLogStageGetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
903 @*/
904 PetscErrorCode PetscLogStageSetVisible(PetscLogStage stage, PetscBool isVisible)
905 
906 {
907   PetscFunctionBegin;
908   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
909     PetscLogHandler h = PetscLogHandlers[i].handler;
910 
911     if (h) PetscCall(PetscLogHandlerStageSetVisible(h, stage, isVisible));
912   }
913   PetscFunctionReturn(PETSC_SUCCESS);
914 }
915 
916 /*@
917   PetscLogStageGetVisible - Returns stage visibility in `PetscLogView()`
918 
919   Not Collective
920 
921   Input Parameter:
922 . stage - The stage
923 
924   Output Parameter:
925 . isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
926 
927   Level: intermediate
928 
929 .seealso: [](ch_profiling), `PetscLogStageSetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
930 @*/
931 PetscErrorCode PetscLogStageGetVisible(PetscLogStage stage, PetscBool *isVisible)
932 {
933   PetscLogHandler handler;
934 
935   PetscFunctionBegin;
936   *isVisible = PETSC_FALSE;
937   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
938   if (handler) { PetscCall(PetscLogHandlerStageGetVisible(handler, stage, isVisible)); }
939   PetscFunctionReturn(PETSC_SUCCESS);
940 }
941 
942 /*@
943   PetscLogStageGetId - Returns the stage id when given the stage name.
944 
945   Not Collective
946 
947   Input Parameter:
948 . name - The stage name
949 
950   Output Parameter:
951 . stage - The stage, , or -1 if no stage with that name exists
952 
953   Level: intermediate
954 
955 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
956 @*/
957 PetscErrorCode PetscLogStageGetId(const char name[], PetscLogStage *stage)
958 {
959   PetscLogState state;
960 
961   PetscFunctionBegin;
962   *stage = -1;
963   PetscCall(PetscLogGetState(&state));
964   if (state) PetscCall(PetscLogStateGetStageFromName(state, name, stage));
965   PetscFunctionReturn(PETSC_SUCCESS);
966 }
967 
968 /*@
969   PetscLogStageGetName - Returns the stage name when given the stage id.
970 
971   Not Collective
972 
973   Input Parameter:
974 . stage - The stage
975 
976   Output Parameter:
977 . name - The stage name
978 
979   Level: intermediate
980 
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;
987 
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 }
996 
997 /*------------------------------------------------ Event Functions --------------------------------------------------*/
998 
999 /*@
1000   PetscLogEventRegister - Registers an event name for logging operations
1001 
1002   Not Collective
1003 
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
1009 
1010   Output Parameter:
1011 . event - The event id for use with `PetscLogEventBegin()` and `PetscLogEventEnd()`.
1012 
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
1025 
1026   Level: intermediate
1027 
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.
1034 
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.
1041 
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.
1046 
1047   If an existing event with the same name exists, its event handle is
1048   returned instead of creating a new event.
1049 
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;
1056 
1057   PetscFunctionBegin;
1058   *event = -1;
1059   PetscCall(PetscLogGetState(&state));
1060   if (state) PetscCall(PetscLogStateEventRegister(state, name, classid, event));
1061   PetscFunctionReturn(PETSC_SUCCESS);
1062 }
1063 
1064 /*@
1065   PetscLogEventSetCollective - Indicates that a particular event is collective.
1066 
1067   Logically Collective
1068 
1069   Input Parameters:
1070 + event      - The event id
1071 - collective - Boolean flag indicating whether a particular event is collective
1072 
1073   Level: developer
1074 
1075   Notes:
1076   New events returned from `PetscLogEventRegister()` are collective by default.
1077 
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.
1081 
1082 .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogEventRegister()`
1083 @*/
1084 PetscErrorCode PetscLogEventSetCollective(PetscLogEvent event, PetscBool collective)
1085 {
1086   PetscLogState state;
1087 
1088   PetscFunctionBegin;
1089   PetscCall(PetscLogGetState(&state));
1090   if (state) PetscCall(PetscLogStateEventSetCollective(state, event, collective));
1091   PetscFunctionReturn(PETSC_SUCCESS);
1092 }
1093 
1094 /*
1095   PetscLogClassSetActiveAll - Activate or inactivate logging for all events associated with a PETSc object class in every stage.
1096 
1097   Not Collective
1098 
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.
1102 
1103   Level: developer
1104 
1105 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`, `PetscLogEventActivateClass()`
1106 */
1107 static PetscErrorCode PetscLogClassSetActiveAll(PetscClassId classid, PetscBool isActive)
1108 {
1109   PetscLogState state;
1110 
1111   PetscFunctionBegin;
1112   PetscCall(PetscLogGetState(&state));
1113   if (state) PetscCall(PetscLogStateClassSetActiveAll(state, classid, isActive));
1114   PetscFunctionReturn(PETSC_SUCCESS);
1115 }
1116 
1117 /*@
1118   PetscLogEventIncludeClass - Activates event logging for a PETSc object class in every stage.
1119 
1120   Not Collective
1121 
1122   Input Parameter:
1123 . classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1124 
1125   Level: developer
1126 
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 }
1135 
1136 /*@
1137   PetscLogEventExcludeClass - Deactivates event logging for a PETSc object class in every stage.
1138 
1139   Not Collective
1140 
1141   Input Parameter:
1142 . classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1143 
1144   Level: developer
1145 
1146   Note:
1147   If a class is excluded then events associated with that class are not logged.
1148 
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 }
1157 
1158 /*
1159   PetscLogEventSetActive - Activate or inactivate logging for an event in a given stage
1160 
1161   Not Collective
1162 
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
1167 
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
1175 
1176   Level: advanced
1177 
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()`.
1181 
1182 .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1183 */
1184 static PetscErrorCode PetscLogEventSetActive(PetscLogStage stage, PetscLogEvent event, PetscBool isActive)
1185 {
1186   PetscLogState state;
1187 
1188   PetscFunctionBegin;
1189   PetscCall(PetscLogGetState(&state));
1190   if (state) PetscCall(PetscLogStateEventSetActive(state, stage, event, isActive));
1191   PetscFunctionReturn(PETSC_SUCCESS);
1192 }
1193 
1194 /*@
1195   PetscLogEventActivate - Indicates that a particular event should be logged.
1196 
1197   Not Collective
1198 
1199   Input Parameter:
1200 . event - The event id
1201 
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
1209 
1210   Level: advanced
1211 
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()`.
1215 
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 }
1224 
1225 /*@
1226   PetscLogEventDeactivate - Indicates that a particular event should not be logged.
1227 
1228   Not Collective
1229 
1230   Input Parameter:
1231 . event - The event id
1232 
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
1240 
1241   Level: advanced
1242 
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()`).
1246 
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 }
1255 
1256 /*@
1257   PetscLogEventDeactivatePush - Indicates that a particular event should not be logged until `PetscLogEventDeactivatePop()` is called
1258 
1259   Not Collective
1260 
1261   Input Parameter:
1262 . event - The event id
1263 
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
1271 
1272   Level: advanced
1273 
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()`).
1277 
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.
1279 
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;
1287 
1288     if (h) PetscCall(PetscLogHandlerEventDeactivatePush(h, PETSC_DEFAULT, event));
1289   }
1290   PetscFunctionReturn(PETSC_SUCCESS);
1291 }
1292 
1293 /*@
1294   PetscLogEventDeactivatePop - Indicates that a particular event should again be logged after the logging was turned off with `PetscLogEventDeactivatePush()`
1295 
1296   Not Collective
1297 
1298   Input Parameter:
1299 . event - The event id
1300 
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
1308 
1309   Level: advanced
1310 
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()`).
1314 
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;
1322 
1323     if (h) PetscCall(PetscLogHandlerEventDeactivatePop(h, PETSC_DEFAULT, event));
1324   }
1325   PetscFunctionReturn(PETSC_SUCCESS);
1326 }
1327 
1328 /*@
1329   PetscLogEventSetActiveAll - Turns on logging of all events
1330 
1331   Not Collective
1332 
1333   Input Parameters:
1334 + event    - The event id
1335 - isActive - The activity flag determining whether the event is logged
1336 
1337   Level: advanced
1338 
1339 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1340 @*/
1341 PetscErrorCode PetscLogEventSetActiveAll(PetscLogEvent event, PetscBool isActive)
1342 {
1343   PetscLogState state;
1344 
1345   PetscFunctionBegin;
1346   PetscCall(PetscLogGetState(&state));
1347   if (state) PetscCall(PetscLogStateEventSetActiveAll(state, event, isActive));
1348   PetscFunctionReturn(PETSC_SUCCESS);
1349 }
1350 
1351 /*
1352   PetscLogClassSetActive - Activates event logging for a PETSc object class for the current stage
1353 
1354   Not Collective
1355 
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.
1360 
1361   Level: developer
1362 
1363 .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`
1364 */
1365 static PetscErrorCode PetscLogClassSetActive(PetscLogStage stage, PetscClassId classid, PetscBool isActive)
1366 {
1367   PetscLogState state;
1368 
1369   PetscFunctionBegin;
1370   PetscCall(PetscLogGetState(&state));
1371   if (state) PetscCall(PetscLogStateClassSetActive(state, stage, classid, isActive));
1372   PetscFunctionReturn(PETSC_SUCCESS);
1373 }
1374 
1375 /*@
1376   PetscLogEventActivateClass - Activates event logging for a PETSc object class for the current stage
1377 
1378   Not Collective
1379 
1380   Input Parameter:
1381 . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1382 
1383   Level: developer
1384 
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 }
1393 
1394 /*@
1395   PetscLogEventDeactivateClass - Deactivates event logging for a PETSc object class for the current stage
1396 
1397   Not Collective
1398 
1399   Input Parameter:
1400 . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1401 
1402   Level: developer
1403 
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 }
1412 
1413 /*MC
1414   PetscLogEventSync - Synchronizes the beginning of a user event.
1415 
1416   Synopsis:
1417   #include <petsclog.h>
1418   PetscErrorCode PetscLogEventSync(PetscLogEvent e, MPI_Comm comm)
1419 
1420   Collective
1421 
1422   Input Parameters:
1423 + e    - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1424 - comm - an MPI communicator
1425 
1426   Example Usage:
1427 .vb
1428   PetscLogEvent USER_EVENT;
1429 
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
1436 
1437   Level: developer
1438 
1439   Note:
1440   This routine should be called only if there is not a `PetscObject` available to pass to
1441   `PetscLogEventBegin()`.
1442 
1443 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`
1444 M*/
1445 
1446 /*MC
1447   PetscLogEventBegin - Logs the beginning of a user event.
1448 
1449   Synopsis:
1450   #include <petsclog.h>
1451   PetscErrorCode PetscLogEventBegin(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
1452 
1453   Not Collective
1454 
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`
1461 
1462   Fortran Synopsis:
1463   void PetscLogEventBegin(int e, PetscErrorCode ierr)
1464 
1465   Example Usage:
1466 .vb
1467   PetscLogEvent USER_EVENT;
1468 
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
1476 
1477   Level: intermediate
1478 
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.
1484 
1485 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventEnd()`, `PetscLogFlops()`
1486 M*/
1487 
1488 /*MC
1489   PetscLogEventEnd - Log the end of a user event.
1490 
1491   Synopsis:
1492   #include <petsclog.h>
1493   PetscErrorCode PetscLogEventEnd(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
1494 
1495   Not Collective
1496 
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`
1503 
1504   Fortran Synopsis:
1505   void PetscLogEventEnd(int e, PetscErrorCode ierr)
1506 
1507   Example Usage:
1508 .vb
1509   PetscLogEvent USER_EVENT;
1510 
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
1518 
1519   Level: intermediate
1520 
1521 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogFlops()`
1522 M*/
1523 
1524 /*@C
1525   PetscLogStageGetPerfInfo - Return the performance information about the given stage
1526 
1527   No Fortran Support
1528 
1529   Input Parameters:
1530 . stage - The stage number or `PETSC_DETERMINE` for the current stage
1531 
1532   Output Parameter:
1533 . info - This structure is filled with the performance information
1534 
1535   Level: intermediate
1536 
1537   Notes:
1538   This is a low level routine used by the logging functions in PETSc.
1539 
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.
1543 
1544 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogGetDefaultHandler()`
1545 @*/
1546 PetscErrorCode PetscLogStageGetPerfInfo(PetscLogStage stage, PetscEventPerfInfo *info)
1547 {
1548   PetscLogHandler     handler;
1549   PetscEventPerfInfo *event_info;
1550 
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 }
1563 
1564 /*@C
1565   PetscLogEventGetPerfInfo - Return the performance information about the given event in the given stage
1566 
1567   No Fortran Support
1568 
1569   Input Parameters:
1570 + stage - The stage number or `PETSC_DETERMINE` for the current stage
1571 - event - The event number
1572 
1573   Output Parameter:
1574 . info - This structure is filled with the performance information
1575 
1576   Level: intermediate
1577 
1578   Note:
1579   This is a low level routine used by the logging functions in PETSc
1580 
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.
1584 
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;
1591 
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 }
1604 
1605 /*@
1606   PetscLogEventSetDof - Set the nth number of degrees of freedom of a numerical problem associated with this event
1607 
1608   Not Collective
1609 
1610   Input Parameters:
1611 + event - The event id to log
1612 . n     - The dof index, in [0, 8)
1613 - dof   - The number of dofs
1614 
1615   Options Database Key:
1616 . -log_view - Activates log summary
1617 
1618   Level: developer
1619 
1620   Note:
1621   This is to enable logging of convergence
1622 
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;
1631 
1632     if (h) {
1633       PetscEventPerfInfo *event_info;
1634 
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 }
1641 
1642 /*@
1643   PetscLogEventSetError - Set the nth error associated with a numerical problem associated with this event
1644 
1645   Not Collective
1646 
1647   Input Parameters:
1648 + event - The event id to log
1649 . n     - The error index, in [0, 8)
1650 - error - The error
1651 
1652   Options Database Key:
1653 . -log_view - Activates log summary
1654 
1655   Level: developer
1656 
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
1660 
1661   This is a low level routine used by the logging functions in PETSc
1662 
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;
1671 
1672     if (h) {
1673       PetscEventPerfInfo *event_info;
1674 
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 }
1681 
1682 /*@
1683   PetscLogEventGetId - Returns the event id when given the event name.
1684 
1685   Not Collective
1686 
1687   Input Parameter:
1688 . name - The event name
1689 
1690   Output Parameter:
1691 . event - The event, or -1 if no event with that name exists
1692 
1693   Level: intermediate
1694 
1695 .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1696 @*/
1697 PetscErrorCode PetscLogEventGetId(const char name[], PetscLogEvent *event)
1698 {
1699   PetscLogState state;
1700 
1701   PetscFunctionBegin;
1702   *event = -1;
1703   PetscCall(PetscLogGetState(&state));
1704   if (state) PetscCall(PetscLogStateGetEventFromName(state, name, event));
1705   PetscFunctionReturn(PETSC_SUCCESS);
1706 }
1707 
1708 /*@
1709   PetscLogEventGetName - Returns the event name when given the event id.
1710 
1711   Not Collective
1712 
1713   Input Parameter:
1714 . event - The event
1715 
1716   Output Parameter:
1717 . name - The event name
1718 
1719   Level: intermediate
1720 
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;
1727 
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 }
1736 
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.
1739 
1740   Not collective
1741 
1742   Level: advanced
1743 
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()`).
1746 
1747   Other log handlers (such as the nested handler, `PetscLogNestedBegin()`) will ignore this function.
1748 
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;
1756 
1757     if (h) PetscCall(PetscLogHandlerEventsPause(h));
1758   }
1759   PetscFunctionReturn(PETSC_SUCCESS);
1760 }
1761 
1762 /*@
1763   PetscLogEventsResume - Return logging to normal behavior after it was paused with `PetscLogEventsPause()`.
1764 
1765   Not collective
1766 
1767   Level: advanced
1768 
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;
1776 
1777     if (h) PetscCall(PetscLogHandlerEventsResume(h));
1778   }
1779   PetscFunctionReturn(PETSC_SUCCESS);
1780 }
1781 
1782 /*------------------------------------------------ Class Functions --------------------------------------------------*/
1783 
1784 /*MC
1785    PetscLogObjectCreate - Log the creation of a `PetscObject`
1786 
1787    Synopsis:
1788    #include <petsclog.h>
1789    PetscErrorCode PetscLogObjectCreate(PetscObject h)
1790 
1791    Not Collective
1792 
1793    Input Parameters:
1794 .  h - A `PetscObject`
1795 
1796    Level: developer
1797 
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.
1801 
1802 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectDestroy()`
1803 M*/
1804 
1805 /*MC
1806    PetscLogObjectDestroy - Logs the destruction of a `PetscObject`
1807 
1808    Synopsis:
1809    #include <petsclog.h>
1810    PetscErrorCode PetscLogObjectDestroy(PetscObject h)
1811 
1812    Not Collective
1813 
1814    Input Parameters:
1815 .  h - A `PetscObject`
1816 
1817    Level: developer
1818 
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.
1822 
1823 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectCreate()`
1824 M*/
1825 
1826 /*@
1827   PetscLogClassGetClassId - Returns the `PetscClassId` when given the class name.
1828 
1829   Not Collective
1830 
1831   Input Parameter:
1832 . name - The class name
1833 
1834   Output Parameter:
1835 . classid - The `PetscClassId` id, or -1 if no class with that name exists
1836 
1837   Level: intermediate
1838 
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;
1846 
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 }
1860 
1861 /*@C
1862   PetscLogClassIdGetName - Returns a `PetscClassId`'s name.
1863 
1864   Not Collective
1865 
1866   Input Parameter:
1867 . classid - A `PetscClassId`
1868 
1869   Output Parameter:
1870 . name - The class name
1871 
1872   Level: intermediate
1873 
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;
1881 
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 }
1889 
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.
1894 
1895   Collective on `PETSC_COMM_WORLD`
1896 
1897   Input Parameter:
1898 . sname - an optional file name
1899 
1900   Example Usage:
1901 .vb
1902   PetscInitialize(...);
1903   PetscLogDefaultBegin();
1904   // ... code ...
1905   PetscLogDump(filename);
1906   PetscFinalize();
1907 .ve
1908 
1909   Level: advanced
1910 
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.
1914 
1915 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
1916 @*/
1917 PetscErrorCode PetscLogDump(const char sname[])
1918 {
1919   PetscLogHandler handler;
1920 
1921   PetscFunctionBegin;
1922   PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1923   PetscCall(PetscLogHandlerDump(handler, sname));
1924   PetscFunctionReturn(PETSC_SUCCESS);
1925 }
1926 
1927 /*@
1928   PetscLogMPEDump - Dumps the MPE logging info to file for later use with Jumpshot.
1929 
1930   Collective on `PETSC_COMM_WORLD`
1931 
1932   Input Parameter:
1933 . sname - filename for the MPE logfile
1934 
1935   Level: advanced
1936 
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];
1945 
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 }
1961 
1962 /*@
1963   PetscLogView - Prints a summary of the logging.
1964 
1965   Collective
1966 
1967   Input Parameter:
1968 . viewer - an ASCII viewer
1969 
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
1979 
1980   Level: beginner
1981 
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.
1985 
1986   Before calling this routine you must have called either PetscLogDefaultBegin() or PetscLogNestedBegin()
1987 
1988   If PETSc is configured with --with-logging=0 then this functionality is not available
1989 
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.
2001 
2002   The nested XML format was kindly donated by Koos Huijssen and Christiaan M. Klaij  MARITIME  RESEARCH  INSTITUTE  NETHERLANDS
2003 
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.
2007 
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;
2019 
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 }
2049 
2050 /*@C
2051   PetscLogViewFromOptions - Processes command line options to determine if/how a `PetscLog` is to be viewed.
2052 
2053   Collective on `PETSC_COMM_WORLD`
2054 
2055   Level: developer
2056 
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;
2065 
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 }
2076 
2077 PETSC_INTERN PetscErrorCode PetscLogHandlerNestedSetThreshold(PetscLogHandler, PetscLogDouble, PetscLogDouble *);
2078 
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.
2082 
2083   Logically Collective on `PETSC_COMM_WORLD`
2084 
2085   Input Parameter:
2086 . newThresh - the threshold to use
2087 
2088   Output Parameter:
2089 . oldThresh - the previously set threshold value
2090 
2091   Options Database Keys:
2092 . -log_view :filename.xml:ascii_xml - Prints an XML summary of flop and timing information to the file
2093 
2094   Example Usage:
2095 .vb
2096   PetscInitialize(...);
2097   PetscLogNestedBegin();
2098   PetscLogSetThreshold(0.1,&oldthresh);
2099   // ... code ...
2100   PetscLogView(viewer);
2101   PetscFinalize();
2102 .ve
2103 
2104   Level: advanced
2105 
2106   Note:
2107   This threshold is only used by the nested log handler
2108 
2109 .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`,
2110           `PetscLogNestedBegin()`
2111 @*/
2112 PetscErrorCode PetscLogSetThreshold(PetscLogDouble newThresh, PetscLogDouble *oldThresh)
2113 {
2114   PetscLogHandler handler;
2115 
2116   PetscFunctionBegin;
2117   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERNESTED, &handler));
2118   PetscCall(PetscLogHandlerNestedSetThreshold(handler, newThresh, oldThresh));
2119   PetscFunctionReturn(PETSC_SUCCESS);
2120 }
2121 
2122 /*----------------------------------------------- Counter Functions -------------------------------------------------*/
2123 /*@
2124   PetscGetFlops - Returns the number of flops used on this processor
2125   since the program began.
2126 
2127   Not Collective
2128 
2129   Output Parameter:
2130 . flops - number of floating point operations
2131 
2132   Level: intermediate
2133 
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.
2138 
2139   A separate counter `PetscLogGpuFlops()` logs the flops that occur on any GPU associated with this MPI rank
2140 
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 }
2149 
2150 /*@C
2151   PetscLogObjectState - Record information about an object with the default log handler
2152 
2153   Not Collective
2154 
2155   Input Parameters:
2156 + obj    - the `PetscObject`
2157 . format - a printf-style format string
2158 - ...    - printf arguments to format
2159 
2160   Level: developer
2161 
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;
2169 
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 }
2179 
2180 /*MC
2181   PetscLogFlops - Adds floating point operations to the global counter.
2182 
2183   Synopsis:
2184   #include <petsclog.h>
2185   PetscErrorCode PetscLogFlops(PetscLogDouble f)
2186 
2187   Not Collective
2188 
2189   Input Parameter:
2190 . f - flop counter
2191 
2192   Example Usage:
2193 .vb
2194   PetscLogEvent USER_EVENT;
2195 
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
2202 
2203   Level: intermediate
2204 
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.
2208 
2209 .seealso: [](ch_profiling), `PetscLogGpuFlops()`, `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscGetFlops()`
2210 M*/
2211 
2212 /*MC
2213   PetscPreLoadBegin - Begin a segment of code that may be preloaded (run twice) to get accurate
2214   timings
2215 
2216   Synopsis:
2217   #include <petsclog.h>
2218   void PetscPreLoadBegin(PetscBool flag, char *name);
2219 
2220   Not Collective
2221 
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
2226 
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
2235 
2236   Level: intermediate
2237 
2238   Note:
2239   Only works in C/C++, not Fortran
2240 
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
2248 
2249   The first two variables are available throughout the program, the second two only between the
2250   `PetscPreLoadBegin()` and `PetscPreLoadEnd()`
2251 
2252 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
2253 M*/
2254 
2255 /*MC
2256   PetscPreLoadEnd - End a segment of code that may be preloaded (run twice) to get accurate
2257   timings
2258 
2259   Synopsis:
2260   #include <petsclog.h>
2261   void PetscPreLoadEnd(void);
2262 
2263   Not Collective
2264 
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
2273 
2274   Level: intermediate
2275 
2276   Note:
2277   Only works in C/C++ not Fortran
2278 
2279 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadStage()`
2280 M*/
2281 
2282 /*MC
2283   PetscPreLoadStage - Start a new segment of code to be timed separately to get accurate timings
2284 
2285   Synopsis:
2286   #include <petsclog.h>
2287   void PetscPreLoadStage(char *name);
2288 
2289   Not Collective
2290 
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
2299 
2300   Level: intermediate
2301 
2302   Note:
2303   Only works in C/C++ not Fortran
2304 
2305 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`
2306 M*/
2307 
2308   #if PetscDefined(HAVE_DEVICE)
2309     #include <petsc/private/deviceimpl.h>
2310 
2311 /*@
2312   PetscLogGpuTime - turn on the logging of GPU time for GPU kernels
2313 
2314   Options Database Key:
2315 . -log_view_gpu_time - provide the GPU times for all events in the `-log_view` output
2316 
2317   Level: advanced
2318 
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.
2323 
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
2325 
2326   This routine should only be called once near the beginning of the program. Once it is started
2327   it cannot be turned off.
2328 
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 }
2338 
2339 /*@
2340   PetscLogGpuTimeBegin - Start timer for device
2341 
2342   Level: intermediate
2343 
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).
2347 
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).
2350 
2351   There is no need to call WaitForCUDA() or WaitForHIP() between `PetscLogGpuTimeBegin()` and
2352   `PetscLogGpuTimeEnd()`
2353 
2354   This timer should NOT include times for data transfers between the GPU and CPU, nor setup
2355   actions such as allocating space.
2356 
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.
2360 
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()`.
2364 
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.
2370 
2371 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTime()`
2372 @*/
2373 PetscErrorCode PetscLogGpuTimeBegin(void)
2374 {
2375   PetscBool isActive;
2376 
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;
2383 
2384     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2385     PetscCall(PetscDeviceContextBeginTimer_Internal(dctx));
2386   }
2387     #else
2388   PetscCall(PetscTimeSubtract(&petsc_gtime));
2389     #endif
2390   PetscFunctionReturn(PETSC_SUCCESS);
2391 }
2392 
2393 /*@
2394   PetscLogGpuTimeEnd - Stop timer for device
2395 
2396   Level: intermediate
2397 
2398 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeBegin()`
2399 @*/
2400 PetscErrorCode PetscLogGpuTimeEnd(void)
2401 {
2402   PetscBool isActive;
2403 
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;
2411 
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 }
2421 
2422   #endif /* end of PETSC_HAVE_DEVICE */
2423 
2424 #endif /* PETSC_USE_LOG*/
2425 
2426 /* -- Utility functions for logging from Fortran -- */
2427 
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 }
2439 
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 }
2451 
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 }
2458 
2459 PetscClassId PETSC_LARGEST_CLASSID = PETSC_SMALLEST_CLASSID;
2460 PetscClassId PETSC_OBJECT_CLASSID  = 0;
2461 
2462 static PetscBool PetscLogInitializeCalled = PETSC_FALSE;
2463 
2464 PETSC_INTERN PetscErrorCode PetscLogInitialize(void)
2465 {
2466   int stage;
2467 
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
2483 
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 }
2491 
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));
2504 
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;
2539 
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 }
2558 
2559 /*@
2560   PetscClassIdRegister - Registers a new class name for objects and logging operations in an application code.
2561 
2562   Not Collective
2563 
2564   Input Parameter:
2565 . name - The class name
2566 
2567   Output Parameter:
2568 . oclass - The class id or classid
2569 
2570   Level: developer
2571 
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;
2582 
2583     PetscCall(PetscLogGetState(&state));
2584     if (state) PetscCall(PetscLogStateClassRegister(state, name, *oclass, &logclass));
2585   }
2586 #endif
2587   PetscFunctionReturn(PETSC_SUCCESS);
2588 }
2589