xref: /petsc/src/sys/logging/plog.c (revision 2ff79c18c26c94ed8cb599682f680f231dca6444)
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 PetscInt PetscLogNumViewersCreated   = 0;
105 PetscInt PetscLogNumViewersDestroyed = 0;
106 
107 PetscLogState petsc_log_state = NULL;
108 
109 #define PETSC_LOG_HANDLER_HOT_BLANK {NULL, NULL, NULL, NULL, NULL, NULL}
110 
111 PetscLogHandlerHot PetscLogHandlers[PETSC_LOG_HANDLER_MAX] = {
112   PETSC_LOG_HANDLER_HOT_BLANK,
113   PETSC_LOG_HANDLER_HOT_BLANK,
114   PETSC_LOG_HANDLER_HOT_BLANK,
115   PETSC_LOG_HANDLER_HOT_BLANK,
116 };
117 
118 #undef PETSC_LOG_HANDLERS_HOT_BLANK
119 
120 #if defined(PETSC_USE_LOG)
121   #include <../src/sys/logging/handler/impls/default/logdefault.h>
122 
123   #if defined(PETSC_HAVE_THREADSAFETY)
124 PetscErrorCode PetscAddLogDouble(PetscLogDouble *tot, PetscLogDouble *tot_th, PetscLogDouble tmp)
125 {
126   *tot_th += tmp;
127   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
128   *tot += tmp;
129   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
130   return PETSC_SUCCESS;
131 }
132 
133 PetscErrorCode PetscAddLogDoubleCnt(PetscLogDouble *cnt, PetscLogDouble *tot, PetscLogDouble *cnt_th, PetscLogDouble *tot_th, PetscLogDouble tmp)
134 {
135   *cnt_th = *cnt_th + 1;
136   *tot_th += tmp;
137   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
138   *tot += (PetscLogDouble)tmp;
139   *cnt += *cnt + 1;
140   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
141   return PETSC_SUCCESS;
142 }
143 
144   #endif
145 
146 static PetscErrorCode PetscLogTryGetHandler(PetscLogHandlerType type, PetscLogHandler *handler)
147 {
148   PetscFunctionBegin;
149   PetscAssertPointer(handler, 2);
150   *handler = NULL;
151   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
152     PetscLogHandler h = PetscLogHandlers[i].handler;
153     if (h) {
154       PetscBool match;
155 
156       PetscCall(PetscObjectTypeCompare((PetscObject)h, type, &match));
157       if (match) {
158         *handler = PetscLogHandlers[i].handler;
159         PetscFunctionReturn(PETSC_SUCCESS);
160       }
161     }
162   }
163   PetscFunctionReturn(PETSC_SUCCESS);
164 }
165 
166 /*@
167   PetscLogGetDefaultHandler - Get the default log handler if it is running.
168 
169   Not collective
170 
171   Output Parameter:
172 . handler - the default `PetscLogHandler`, or `NULL` if it is not running.
173 
174   Level: developer
175 
176   Notes:
177   The default handler is started with `PetscLogDefaultBegin()`,
178   if the options flags `-log_all` or `-log_view` is given without arguments,
179   or for `-log_view :output:format` if `format` is not `ascii_xml` or `ascii_flamegraph`.
180 
181 .seealso: [](ch_profiling)
182 @*/
183 PetscErrorCode PetscLogGetDefaultHandler(PetscLogHandler *handler)
184 {
185   PetscFunctionBegin;
186   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, handler));
187   PetscFunctionReturn(PETSC_SUCCESS);
188 }
189 
190 static PetscErrorCode PetscLogGetHandler(PetscLogHandlerType type, PetscLogHandler *handler)
191 {
192   PetscFunctionBegin;
193   PetscAssertPointer(handler, 2);
194   PetscCall(PetscLogTryGetHandler(type, handler));
195   PetscCheck(*handler != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "A PetscLogHandler of type %s has not been started.", type);
196   PetscFunctionReturn(PETSC_SUCCESS);
197 }
198 
199 /*@
200   PetscLogGetState - Get the `PetscLogState` for PETSc's global logging, used
201   by all default log handlers (`PetscLogDefaultBegin()`,
202   `PetscLogNestedBegin()`, `PetscLogTraceBegin()`, `PetscLogMPEBegin()`,
203   `PetscLogPerfstubsBegin()`).
204 
205   Collective on `PETSC_COMM_WORLD`
206 
207   Output Parameter:
208 . state - The `PetscLogState` changed by registrations (such as
209           `PetscLogEventRegister()`) and actions (such as `PetscLogEventBegin()` or
210           `PetscLogStagePush()`), or `NULL` if logging is not active
211 
212   Level: developer
213 
214 .seealso: [](ch_profiling), `PetscLogState`
215 @*/
216 PetscErrorCode PetscLogGetState(PetscLogState *state)
217 {
218   PetscFunctionBegin;
219   PetscAssertPointer(state, 1);
220   *state = petsc_log_state;
221   PetscFunctionReturn(PETSC_SUCCESS);
222 }
223 
224 static PetscErrorCode PetscLogHandlerCopyToHot(PetscLogHandler h, PetscLogHandlerHot *hot)
225 {
226   PetscFunctionBegin;
227   hot->handler       = h;
228   hot->eventBegin    = h->ops->eventbegin;
229   hot->eventEnd      = h->ops->eventend;
230   hot->eventSync     = h->ops->eventsync;
231   hot->objectCreate  = h->ops->objectcreate;
232   hot->objectDestroy = h->ops->objectdestroy;
233   PetscFunctionReturn(PETSC_SUCCESS);
234 }
235 
236 /*@
237   PetscLogHandlerStart - Connect a log handler to PETSc's global logging stream and state.
238 
239   Logically collective
240 
241   Input Parameters:
242 . h - a `PetscLogHandler`
243 
244   Level: developer
245 
246   Notes:
247   Users should only need this if they create their own log handlers: handlers that are started
248   from the command line (such as `-log_view` and `-log_trace`) or from a function like
249   `PetscLogNestedBegin()` will automatically be started.
250 
251   There is a limit of `PESC_LOG_HANDLER_MAX` handlers that can be active at one time.
252 
253   To disconnect a handler from the global stream call `PetscLogHandlerStop()`.
254 
255   When a log handler is started, stages that have already been pushed with `PetscLogStagePush()`,
256   will be pushed for the new log handler, but it will not be informed of any events that are
257   in progress.  It is recommended to start any user-defined log handlers immediately following
258   `PetscInitialize()`  before any user-defined stages are pushed.
259 
260 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogState`, `PetscLogHandlerStop()`, `PetscInitialize()`
261 @*/
262 PetscErrorCode PetscLogHandlerStart(PetscLogHandler h)
263 {
264   PetscFunctionBegin;
265   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
266     if (PetscLogHandlers[i].handler == h) PetscFunctionReturn(PETSC_SUCCESS);
267   }
268   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
269     if (PetscLogHandlers[i].handler == NULL) {
270       PetscCall(PetscObjectReference((PetscObject)h));
271       PetscCall(PetscLogHandlerCopyToHot(h, &PetscLogHandlers[i]));
272       if (petsc_log_state) {
273         PetscLogStage stack_height;
274         PetscIntStack orig_stack, temp_stack;
275 
276         PetscCall(PetscLogHandlerSetState(h, petsc_log_state));
277         stack_height = petsc_log_state->stage_stack->top + 1;
278         PetscCall(PetscIntStackCreate(&temp_stack));
279         orig_stack                     = petsc_log_state->stage_stack;
280         petsc_log_state->stage_stack   = temp_stack;
281         petsc_log_state->current_stage = -1;
282         for (int s = 0; s < stack_height; s++) {
283           PetscLogStage stage = orig_stack->stack[s];
284           PetscCall(PetscLogHandlerStagePush(h, stage));
285           PetscCall(PetscIntStackPush(temp_stack, stage));
286           petsc_log_state->current_stage = stage;
287         }
288         PetscCall(PetscIntStackDestroy(temp_stack));
289         petsc_log_state->stage_stack = orig_stack;
290       }
291       PetscFunctionReturn(PETSC_SUCCESS);
292     }
293   }
294   SETERRQ(PetscObjectComm((PetscObject)h), PETSC_ERR_ARG_WRONGSTATE, "%d log handlers already started, cannot start another", PETSC_LOG_HANDLER_MAX);
295   PetscFunctionReturn(PETSC_SUCCESS);
296 }
297 
298 /*@
299   PetscLogHandlerStop - Disconnect a log handler from PETSc's global logging stream.
300 
301   Logically collective
302 
303   Input Parameters:
304 . h - a `PetscLogHandler`
305 
306   Level: developer
307 
308   Note:
309   After `PetscLogHandlerStop()`, the handler can still access the global logging state
310   with `PetscLogHandlerGetState()`, so that it can access the registry when post-processing
311   (for instance, in `PetscLogHandlerView()`),
312 
313   When a log handler is stopped, the remaining stages will be popped before it is
314   disconnected from the log stream.
315 
316 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogState`, `PetscLogHandlerStart()`
317 @*/
318 PetscErrorCode PetscLogHandlerStop(PetscLogHandler h)
319 {
320   PetscFunctionBegin;
321   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
322     if (PetscLogHandlers[i].handler == h) {
323       if (petsc_log_state) {
324         PetscLogState state;
325         PetscLogStage stack_height;
326         PetscIntStack orig_stack, temp_stack;
327 
328         PetscCall(PetscLogHandlerGetState(h, &state));
329         PetscCheck(state == petsc_log_state, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "Called PetscLogHandlerStop() for a PetscLogHander that was not started.");
330         stack_height = petsc_log_state->stage_stack->top + 1;
331         PetscCall(PetscIntStackCreate(&temp_stack));
332         orig_stack                   = petsc_log_state->stage_stack;
333         petsc_log_state->stage_stack = temp_stack;
334         for (int s = 0; s < stack_height; s++) {
335           PetscLogStage stage = orig_stack->stack[s];
336 
337           PetscCall(PetscIntStackPush(temp_stack, stage));
338         }
339         for (int s = 0; s < stack_height; s++) {
340           PetscLogStage stage;
341           PetscBool     empty;
342 
343           PetscCall(PetscIntStackPop(temp_stack, &stage));
344           PetscCall(PetscIntStackEmpty(temp_stack, &empty));
345           if (!empty) PetscCall(PetscIntStackTop(temp_stack, &petsc_log_state->current_stage));
346           else petsc_log_state->current_stage = -1;
347           PetscCall(PetscLogHandlerStagePop(h, stage));
348         }
349         PetscCall(PetscIntStackDestroy(temp_stack));
350         petsc_log_state->stage_stack = orig_stack;
351         PetscCall(PetscIntStackTop(petsc_log_state->stage_stack, &petsc_log_state->current_stage));
352       }
353       PetscCall(PetscArrayzero(&PetscLogHandlers[i], 1));
354       PetscCall(PetscObjectDereference((PetscObject)h));
355     }
356   }
357   PetscFunctionReturn(PETSC_SUCCESS);
358 }
359 
360 /*@
361   PetscLogIsActive - Check if logging (profiling) is currently in progress.
362 
363   Not Collective
364 
365   Output Parameter:
366 . isActive - `PETSC_TRUE` if logging is in progress, `PETSC_FALSE` otherwise
367 
368   Level: beginner
369 
370 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`
371 @*/
372 PetscErrorCode PetscLogIsActive(PetscBool *isActive)
373 {
374   PetscFunctionBegin;
375   *isActive = PETSC_FALSE;
376   if (petsc_log_state) {
377     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
378       if (PetscLogHandlers[i].handler) {
379         *isActive = PETSC_TRUE;
380         PetscFunctionReturn(PETSC_SUCCESS);
381       }
382     }
383   }
384   PetscFunctionReturn(PETSC_SUCCESS);
385 }
386 
387 PETSC_UNUSED static PetscErrorCode PetscLogEventBeginIsActive(PetscBool *isActive)
388 {
389   PetscFunctionBegin;
390   *isActive = PETSC_FALSE;
391   if (petsc_log_state) {
392     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
393       if (PetscLogHandlers[i].eventBegin) {
394         *isActive = PETSC_TRUE;
395         PetscFunctionReturn(PETSC_SUCCESS);
396       }
397     }
398   }
399   PetscFunctionReturn(PETSC_SUCCESS);
400 }
401 
402 PETSC_UNUSED static PetscErrorCode PetscLogEventEndIsActive(PetscBool *isActive)
403 {
404   PetscFunctionBegin;
405   *isActive = PETSC_FALSE;
406   if (petsc_log_state) {
407     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
408       if (PetscLogHandlers[i].eventEnd) {
409         *isActive = PETSC_TRUE;
410         PetscFunctionReturn(PETSC_SUCCESS);
411       }
412     }
413   }
414   PetscFunctionReturn(PETSC_SUCCESS);
415 }
416 
417 PETSC_INTERN PetscErrorCode PetscLogTypeBegin(PetscLogHandlerType type)
418 {
419   PetscLogHandler handler;
420 
421   PetscFunctionBegin;
422   PetscCall(PetscLogTryGetHandler(type, &handler));
423   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
424   PetscCall(PetscLogHandlerCreate(PETSC_COMM_WORLD, &handler));
425   PetscCall(PetscLogHandlerSetType(handler, type));
426   PetscCall(PetscLogHandlerStart(handler));
427   PetscCall(PetscLogHandlerDestroy(&handler));
428   PetscFunctionReturn(PETSC_SUCCESS);
429 }
430 
431 /*@
432   PetscLogDefaultBegin - Turns on logging (profiling) of PETSc code using the default log handler (profiler). This logs time, flop
433   rates, and object creation and should not slow programs down too much.
434 
435   Logically Collective on `PETSC_COMM_WORLD`
436 
437   Options Database Key:
438 . -log_view [viewertype:filename:viewerformat] - Prints summary of flop and timing (profiling) information to the
439                                                  screen (for PETSc configured with `--with-log=1` (which is the default)).
440                                                  This option must be provided before `PetscInitialize()`.
441 
442   Example Usage:
443 .vb
444       PetscInitialize(...);
445       PetscLogDefaultBegin();
446        ... code ...
447       PetscLogView(viewer); or PetscLogDump();
448       PetscFinalize();
449 .ve
450 
451   Level: advanced
452 
453   Notes:
454   `PetscLogView()` or `PetscLogDump()` actually cause the printing of
455   the logging information.
456 
457   This routine may be called more than once.
458 
459   To provide the `-log_view` option in your source code you must call  PetscCall(PetscOptionsSetValue(NULL, "-log_view", NULL));
460   before you call `PetscInitialize()`
461 
462 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`
463 @*/
464 PetscErrorCode PetscLogDefaultBegin(void)
465 {
466   PetscFunctionBegin;
467   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERDEFAULT));
468   PetscFunctionReturn(PETSC_SUCCESS);
469 }
470 
471 /*@C
472   PetscLogTraceBegin - Begins trace logging.  Every time a PETSc event
473   begins or ends, the event name is printed.
474 
475   Logically Collective on `PETSC_COMM_WORLD`, No Fortran Support
476 
477   Input Parameter:
478 . file - The file to print trace in (e.g. stdout)
479 
480   Options Database Key:
481 . -log_trace [filename] - Begins `PetscLogTraceBegin()`
482 
483   Level: intermediate
484 
485   Notes:
486   `PetscLogTraceBegin()` prints the processor number, the execution time (sec),
487   then "Event begin:" or "Event end:" followed by the event name.
488 
489   `PetscLogTraceBegin()` allows tracing of all PETSc calls, which is useful
490   to determine where a program is hanging without running in the
491   debugger.  Can be used in conjunction with the -info option.
492 
493 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogDefaultBegin()`
494 @*/
495 PetscErrorCode PetscLogTraceBegin(FILE *file)
496 {
497   PetscLogHandler handler;
498 
499   PetscFunctionBegin;
500   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERTRACE, &handler));
501   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
502   PetscCall(PetscLogHandlerCreateTrace(PETSC_COMM_WORLD, file, &handler));
503   PetscCall(PetscLogHandlerStart(handler));
504   PetscCall(PetscLogHandlerDestroy(&handler));
505   PetscFunctionReturn(PETSC_SUCCESS);
506 }
507 
508 PETSC_INTERN PetscErrorCode PetscLogHandlerCreate_Nested(MPI_Comm, PetscLogHandler *);
509 
510 /*@
511   PetscLogNestedBegin - Turns on nested logging of objects and events. This logs flop
512   rates and object creation and should not slow programs down too much.
513 
514   Logically Collective on `PETSC_COMM_WORLD`, No Fortran Support
515 
516   Options Database Keys:
517 . -log_view :filename.xml:ascii_xml - Prints an XML summary of flop and timing information to the file
518 
519   Example Usage:
520 .vb
521       PetscInitialize(...);
522       PetscLogNestedBegin();
523        ... code ...
524       PetscLogView(viewer);
525       PetscFinalize();
526 .ve
527 
528   Level: advanced
529 
530 .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`
531 @*/
532 PetscErrorCode PetscLogNestedBegin(void)
533 {
534   PetscFunctionBegin;
535   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERNESTED));
536   PetscFunctionReturn(PETSC_SUCCESS);
537 }
538 
539 /*@C
540   PetscLogLegacyCallbacksBegin - Create and start a log handler from callbacks
541   matching the now deprecated function pointers `PetscLogPLB`, `PetscLogPLE`,
542   `PetscLogPHC`, `PetscLogPHD`.
543 
544   Logically Collective on `PETSC_COMM_WORLD`
545 
546   Input Parameters:
547 + PetscLogPLB - A callback that will be executed by `PetscLogEventBegin()` (or `NULL`)
548 . PetscLogPLE - A callback that will be executed by `PetscLogEventEnd()` (or `NULL`)
549 . PetscLogPHC - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)
550 - PetscLogPHD - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)
551 
552   Calling sequence of `PetscLogPLB`:
553 + e  - a `PetscLogEvent` that is beginning
554 . _i - deprecated, unused
555 . o1 - a `PetscObject` associated with `e` (or `NULL`)
556 . o2 - a `PetscObject` associated with `e` (or `NULL`)
557 . o3 - a `PetscObject` associated with `e` (or `NULL`)
558 - o4 - a `PetscObject` associated with `e` (or `NULL`)
559 
560   Calling sequence of `PetscLogPLE`:
561 + e  - a `PetscLogEvent` that is beginning
562 . _i - deprecated, unused
563 . o1 - a `PetscObject` associated with `e` (or `NULL`)
564 . o2 - a `PetscObject` associated with `e` (or `NULL`)
565 . o3 - a `PetscObject` associated with `e` (or `NULL`)
566 - o4 - a `PetscObject` associated with `e` (or `NULL`)
567 
568   Calling sequence of `PetscLogPHC`:
569 . o - a `PetscObject` that has just been created
570 
571   Calling sequence of `PetscLogPHD`:
572 . o - a `PetscObject` that is about to be destroyed
573 
574   Level: advanced
575 
576   Notes:
577   This is for transitioning from the deprecated function `PetscLogSet()` and should not be used in new code.
578 
579   This should help migrate external log handlers to use `PetscLogHandler`, but
580   callbacks that depend on the deprecated `PetscLogStage` datatype will have to be
581   updated.
582 
583 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogHandlerStart()`, `PetscLogState`
584 @*/
585 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))
586 {
587   PetscLogHandler handler;
588 
589   PetscFunctionBegin;
590   PetscCall(PetscLogHandlerCreateLegacy(PETSC_COMM_WORLD, PetscLogPLB, PetscLogPLE, PetscLogPHC, PetscLogPHD, &handler));
591   PetscCall(PetscLogHandlerStart(handler));
592   PetscCall(PetscLogHandlerDestroy(&handler));
593   PetscFunctionReturn(PETSC_SUCCESS);
594 }
595 
596   #if defined(PETSC_HAVE_MPE)
597     #include <mpe.h>
598 static PetscBool PetscBeganMPE = PETSC_FALSE;
599   #endif
600 
601 /*@C
602   PetscLogMPEBegin - Turns on MPE logging of events. This creates large log files and slows the
603   program down.
604 
605   Collective on `PETSC_COMM_WORLD`, No Fortran Support
606 
607   Options Database Key:
608 . -log_mpe - Prints extensive log information
609 
610   Level: advanced
611 
612   Note:
613   A related routine is `PetscLogDefaultBegin()` (with the options key `-log_view`), which is
614   intended for production runs since it logs only flop rates and object creation (and should
615   not significantly slow the programs).
616 
617 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogDefaultBegin()`, `PetscLogEventActivate()`,
618           `PetscLogEventDeactivate()`
619 @*/
620 PetscErrorCode PetscLogMPEBegin(void)
621 {
622   PetscFunctionBegin;
623   #if defined(PETSC_HAVE_MPE)
624   /* Do MPE initialization */
625   if (!MPE_Initialized_logging()) { /* This function exists in mpich 1.1.2 and higher */
626     PetscCall(PetscInfo(0, "Initializing MPE.\n"));
627     PetscCall(MPE_Init_log());
628 
629     PetscBeganMPE = PETSC_TRUE;
630   } else {
631     PetscCall(PetscInfo(0, "MPE already initialized. Not attempting to reinitialize.\n"));
632   }
633   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERMPE));
634   #else
635   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
636   #endif
637   PetscFunctionReturn(PETSC_SUCCESS);
638 }
639 
640   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
641     #include <../src/sys/perfstubs/timer.h>
642   #endif
643 
644 /*@C
645   PetscLogPerfstubsBegin - Turns on logging of events using the perfstubs interface.
646 
647   Collective on `PETSC_COMM_WORLD`, No Fortran Support
648 
649   Options Database Key:
650 . -log_perfstubs - use an external log handler through the perfstubs interface
651 
652   Level: advanced
653 
654 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogEventActivate()`
655 @*/
656 PetscErrorCode PetscLogPerfstubsBegin(void)
657 {
658   PetscFunctionBegin;
659   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
660   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERPERFSTUBS));
661   #else
662   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without perfstubs support, reconfigure with --with-tau-perfstubs");
663   #endif
664   PetscFunctionReturn(PETSC_SUCCESS);
665 }
666 
667 /*@
668   PetscLogActions - Determines whether actions are logged for the default log handler.
669 
670   Not Collective
671 
672   Input Parameter:
673 . flag - `PETSC_TRUE` if actions are to be logged
674 
675   Options Database Key:
676 + -log_exclude_actions - (deprecated) Does nothing
677 - -log_include_actions - Turn on action logging
678 
679   Level: intermediate
680 
681   Note:
682   Logging of actions continues to consume more memory as the program
683   runs. Long running programs should consider turning this feature off.
684 
685 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogGetDefaultHandler()`
686 @*/
687 PetscErrorCode PetscLogActions(PetscBool flag)
688 {
689   PetscFunctionBegin;
690   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
691     PetscLogHandler h = PetscLogHandlers[i].handler;
692 
693     if (h) PetscCall(PetscLogHandlerSetLogActions(h, flag));
694   }
695   PetscFunctionReturn(PETSC_SUCCESS);
696 }
697 
698 /*@
699   PetscLogObjects - Determines whether objects are logged for the graphical viewer.
700 
701   Not Collective
702 
703   Input Parameter:
704 . flag - `PETSC_TRUE` if objects are to be logged
705 
706   Options Database Key:
707 + -log_exclude_objects - (deprecated) Does nothing
708 - -log_include_objects - Turns on object logging
709 
710   Level: intermediate
711 
712   Note:
713   Logging of objects continues to consume more memory as the program
714   runs. Long running programs should consider turning this feature off.
715 
716 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogGetDefaultHandler()`
717 @*/
718 PetscErrorCode PetscLogObjects(PetscBool flag)
719 {
720   PetscFunctionBegin;
721   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
722     PetscLogHandler h = PetscLogHandlers[i].handler;
723 
724     if (h) PetscCall(PetscLogHandlerSetLogObjects(h, flag));
725   }
726   PetscFunctionReturn(PETSC_SUCCESS);
727 }
728 
729 /*------------------------------------------------ Stage Functions --------------------------------------------------*/
730 /*@
731   PetscLogStageRegister - Attaches a character string name to a logging stage.
732 
733   Not Collective
734 
735   Input Parameter:
736 . sname - The name to associate with that stage
737 
738   Output Parameter:
739 . stage - The stage number or -1 if logging is not active (`PetscLogIsActive()`).
740 
741   Level: intermediate
742 
743 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`
744 @*/
745 PetscErrorCode PetscLogStageRegister(const char sname[], PetscLogStage *stage)
746 {
747   PetscLogState state;
748 
749   PetscFunctionBegin;
750   *stage = -1;
751   PetscCall(PetscLogGetState(&state));
752   if (state) PetscCall(PetscLogStateStageRegister(state, sname, stage));
753   PetscFunctionReturn(PETSC_SUCCESS);
754 }
755 
756 /*@
757   PetscLogStagePush - This function pushes a stage on the logging stack. Events started and stopped until `PetscLogStagePop()` will be associated with the stage
758 
759   Not Collective
760 
761   Input Parameter:
762 . stage - The stage on which to log
763 
764   Example Usage:
765   If the option -log_view is used to run the program containing the
766   following code, then 2 sets of summary data will be printed during
767   PetscFinalize().
768 .vb
769       PetscInitialize(int *argc,char ***args,0,0);
770       [stage 0 of code]
771       PetscLogStagePush(1);
772       [stage 1 of code]
773       PetscLogStagePop();
774       PetscBarrier(...);
775       [more stage 0 of code]
776       PetscFinalize();
777 .ve
778 
779   Level: intermediate
780 
781   Note:
782   Use `PetscLogStageRegister()` to register a stage.
783 
784 .seealso: [](ch_profiling), `PetscLogStagePop()`, `PetscLogStageRegister()`, `PetscBarrier()`
785 @*/
786 PetscErrorCode PetscLogStagePush(PetscLogStage stage)
787 {
788   PetscLogState state;
789 
790   PetscFunctionBegin;
791   PetscCall(PetscLogGetState(&state));
792   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
793   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
794     PetscLogHandler h = PetscLogHandlers[i].handler;
795     if (h) PetscCall(PetscLogHandlerStagePush(h, stage));
796   }
797   PetscCall(PetscLogStateStagePush(state, stage));
798   PetscFunctionReturn(PETSC_SUCCESS);
799 }
800 
801 /*@
802   PetscLogStagePop - This function pops a stage from the logging stack that was pushed with `PetscLogStagePush()`
803 
804   Not Collective
805 
806   Example Usage:
807   If the option -log_view is used to run the program containing the
808   following code, then 2 sets of summary data will be printed during
809   PetscFinalize().
810 .vb
811       PetscInitialize(int *argc,char ***args,0,0);
812       [stage 0 of code]
813       PetscLogStagePush(1);
814       [stage 1 of code]
815       PetscLogStagePop();
816       PetscBarrier(...);
817       [more stage 0 of code]
818       PetscFinalize();
819 .ve
820 
821   Level: intermediate
822 
823 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStageRegister()`, `PetscBarrier()`
824 @*/
825 PetscErrorCode PetscLogStagePop(void)
826 {
827   PetscLogState state;
828   PetscLogStage current_stage;
829 
830   PetscFunctionBegin;
831   PetscCall(PetscLogGetState(&state));
832   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
833   current_stage = state->current_stage;
834   PetscCall(PetscLogStateStagePop(state));
835   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
836     PetscLogHandler h = PetscLogHandlers[i].handler;
837     if (h) PetscCall(PetscLogHandlerStagePop(h, current_stage));
838   }
839   PetscFunctionReturn(PETSC_SUCCESS);
840 }
841 
842 /*@
843   PetscLogStageSetActive - Sets if a stage is used for `PetscLogEventBegin()` and `PetscLogEventEnd()`.
844 
845   Not Collective
846 
847   Input Parameters:
848 + stage    - The stage
849 - isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
850 
851   Level: intermediate
852 
853   Note:
854   If this is set to `PETSC_FALSE` the logging acts as if the stage did not exist
855 
856 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
857 @*/
858 PetscErrorCode PetscLogStageSetActive(PetscLogStage stage, PetscBool isActive)
859 {
860   PetscLogState state;
861 
862   PetscFunctionBegin;
863   PetscCall(PetscLogGetState(&state));
864   if (state) PetscCall(PetscLogStateStageSetActive(state, stage, isActive));
865   PetscFunctionReturn(PETSC_SUCCESS);
866 }
867 
868 /*@
869   PetscLogStageGetActive - Checks if a stage is used for `PetscLogEventBegin()` and `PetscLogEventEnd()`.
870 
871   Not Collective
872 
873   Input Parameter:
874 . stage - The stage
875 
876   Output Parameter:
877 . isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
878 
879   Level: intermediate
880 
881 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
882 @*/
883 PetscErrorCode PetscLogStageGetActive(PetscLogStage stage, PetscBool *isActive)
884 {
885   PetscLogState state;
886 
887   PetscFunctionBegin;
888   *isActive = PETSC_FALSE;
889   PetscCall(PetscLogGetState(&state));
890   if (state) PetscCall(PetscLogStateStageGetActive(state, stage, isActive));
891   PetscFunctionReturn(PETSC_SUCCESS);
892 }
893 
894 /*@
895   PetscLogStageSetVisible - Determines stage visibility in `PetscLogView()`
896 
897   Not Collective
898 
899   Input Parameters:
900 + stage     - The stage
901 - isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
902 
903   Level: intermediate
904 
905   Developer Notes:
906   Visibility only affects the default log handler in `PetscLogView()`: stages that are
907   set to invisible are suppressed from output.
908 
909 .seealso: [](ch_profiling), `PetscLogStageGetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
910 @*/
911 PetscErrorCode PetscLogStageSetVisible(PetscLogStage stage, PetscBool isVisible)
912 
913 {
914   PetscFunctionBegin;
915   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
916     PetscLogHandler h = PetscLogHandlers[i].handler;
917 
918     if (h) PetscCall(PetscLogHandlerStageSetVisible(h, stage, isVisible));
919   }
920   PetscFunctionReturn(PETSC_SUCCESS);
921 }
922 
923 /*@
924   PetscLogStageGetVisible - Returns stage visibility in `PetscLogView()`
925 
926   Not Collective
927 
928   Input Parameter:
929 . stage - The stage
930 
931   Output Parameter:
932 . isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
933 
934   Level: intermediate
935 
936 .seealso: [](ch_profiling), `PetscLogStageSetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
937 @*/
938 PetscErrorCode PetscLogStageGetVisible(PetscLogStage stage, PetscBool *isVisible)
939 {
940   PetscLogHandler handler;
941 
942   PetscFunctionBegin;
943   *isVisible = PETSC_FALSE;
944   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
945   if (handler) PetscCall(PetscLogHandlerStageGetVisible(handler, stage, isVisible));
946   PetscFunctionReturn(PETSC_SUCCESS);
947 }
948 
949 /*@
950   PetscLogStageGetId - Returns the stage id when given the stage name.
951 
952   Not Collective
953 
954   Input Parameter:
955 . name - The stage name
956 
957   Output Parameter:
958 . stage - The stage, , or -1 if no stage with that name exists
959 
960   Level: intermediate
961 
962 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
963 @*/
964 PetscErrorCode PetscLogStageGetId(const char name[], PetscLogStage *stage)
965 {
966   PetscLogState state;
967 
968   PetscFunctionBegin;
969   *stage = -1;
970   PetscCall(PetscLogGetState(&state));
971   if (state) PetscCall(PetscLogStateGetStageFromName(state, name, stage));
972   PetscFunctionReturn(PETSC_SUCCESS);
973 }
974 
975 /*@
976   PetscLogStageGetName - Returns the stage name when given the stage id.
977 
978   Not Collective
979 
980   Input Parameter:
981 . stage - The stage
982 
983   Output Parameter:
984 . name - The stage name
985 
986   Level: intermediate
987 
988 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
989 @*/
990 PetscErrorCode PetscLogStageGetName(PetscLogStage stage, const char *name[])
991 {
992   PetscLogStageInfo stage_info;
993   PetscLogState     state;
994 
995   PetscFunctionBegin;
996   *name = NULL;
997   PetscCall(PetscLogGetState(&state));
998   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
999   PetscCall(PetscLogStateStageGetInfo(state, stage, &stage_info));
1000   *name = stage_info.name;
1001   PetscFunctionReturn(PETSC_SUCCESS);
1002 }
1003 
1004 /*------------------------------------------------ Event Functions --------------------------------------------------*/
1005 
1006 /*@
1007   PetscLogEventRegister - Registers an event name for logging operations
1008 
1009   Not Collective
1010 
1011   Input Parameters:
1012 + name    - The name associated with the event
1013 - classid - The classid associated to the class for this event, obtain either with
1014            `PetscClassIdRegister()` or use a predefined one such as `KSP_CLASSID`, `SNES_CLASSID`, the predefined ones
1015            are only available in C code
1016 
1017   Output Parameter:
1018 . event - The event id for use with `PetscLogEventBegin()` and `PetscLogEventEnd()`.
1019 
1020   Example Usage:
1021 .vb
1022       PetscLogEvent USER_EVENT;
1023       PetscClassId classid;
1024       PetscLogDouble user_event_flops;
1025       PetscClassIdRegister("class name",&classid);
1026       PetscLogEventRegister("User event name",classid,&USER_EVENT);
1027       PetscLogEventBegin(USER_EVENT,0,0,0,0);
1028          [code segment to monitor]
1029          PetscLogFlops(user_event_flops);
1030       PetscLogEventEnd(USER_EVENT,0,0,0,0);
1031 .ve
1032 
1033   Level: intermediate
1034 
1035   Notes:
1036   PETSc automatically logs library events if the code has been
1037   configured with --with-log (which is the default) and
1038   -log_view or -log_all is specified.  `PetscLogEventRegister()` is
1039   intended for logging user events to supplement this PETSc
1040   information.
1041 
1042   PETSc can gather data for use with the utilities Jumpshot
1043   (part of the MPICH distribution).  If PETSc has been compiled
1044   with flag -DPETSC_HAVE_MPE (MPE is an additional utility within
1045   MPICH), the user can employ another command line option, -log_mpe,
1046   to create a logfile, "mpe.log", which can be visualized
1047   Jumpshot.
1048 
1049   The classid is associated with each event so that classes of events
1050   can be disabled simultaneously, such as all matrix events. The user
1051   can either use an existing classid, such as `MAT_CLASSID`, or create
1052   their own as shown in the example.
1053 
1054   If an existing event with the same name exists, its event handle is
1055   returned instead of creating a new event.
1056 
1057 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogFlops()`,
1058           `PetscLogEventActivate()`, `PetscLogEventDeactivate()`, `PetscClassIdRegister()`
1059 @*/
1060 PetscErrorCode PetscLogEventRegister(const char name[], PetscClassId classid, PetscLogEvent *event)
1061 {
1062   PetscLogState state;
1063 
1064   PetscFunctionBegin;
1065   *event = -1;
1066   PetscCall(PetscLogGetState(&state));
1067   if (state) PetscCall(PetscLogStateEventRegister(state, name, classid, event));
1068   PetscFunctionReturn(PETSC_SUCCESS);
1069 }
1070 
1071 /*@
1072   PetscLogEventSetCollective - Indicates that a particular event is collective.
1073 
1074   Logically Collective
1075 
1076   Input Parameters:
1077 + event      - The event id
1078 - collective - `PetscBool` indicating whether a particular event is collective
1079 
1080   Level: developer
1081 
1082   Notes:
1083   New events returned from `PetscLogEventRegister()` are collective by default.
1084 
1085   Collective events are handled specially if the command line option `-log_sync` is used. In that case the logging saves information about
1086   two parts of the event; the time for all the MPI ranks to synchronize and then the time for the actual computation/communication
1087   to be performed. This option is useful to debug imbalance within the computations or communications.
1088 
1089 .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogEventRegister()`
1090 @*/
1091 PetscErrorCode PetscLogEventSetCollective(PetscLogEvent event, PetscBool collective)
1092 {
1093   PetscLogState state;
1094 
1095   PetscFunctionBegin;
1096   PetscCall(PetscLogGetState(&state));
1097   if (state) PetscCall(PetscLogStateEventSetCollective(state, event, collective));
1098   PetscFunctionReturn(PETSC_SUCCESS);
1099 }
1100 
1101 /*
1102   PetscLogClassSetActiveAll - Activate or inactivate logging for all events associated with a PETSc object class in every stage.
1103 
1104   Not Collective
1105 
1106   Input Parameters:
1107 + classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1108 - isActive - if `PETSC_FALSE`, events associated with this class will not be send to log handlers.
1109 
1110   Level: developer
1111 
1112 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`, `PetscLogEventActivateClass()`
1113 */
1114 static PetscErrorCode PetscLogClassSetActiveAll(PetscClassId classid, PetscBool isActive)
1115 {
1116   PetscLogState state;
1117 
1118   PetscFunctionBegin;
1119   PetscCall(PetscLogGetState(&state));
1120   if (state) PetscCall(PetscLogStateClassSetActiveAll(state, classid, isActive));
1121   PetscFunctionReturn(PETSC_SUCCESS);
1122 }
1123 
1124 /*@
1125   PetscLogEventIncludeClass - Activates event logging for a PETSc object class in every stage.
1126 
1127   Not Collective
1128 
1129   Input Parameter:
1130 . classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1131 
1132   Level: developer
1133 
1134 .seealso: [](ch_profiling), `PetscLogEventActivateClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1135 @*/
1136 PetscErrorCode PetscLogEventIncludeClass(PetscClassId classid)
1137 {
1138   PetscFunctionBegin;
1139   PetscCall(PetscLogClassSetActiveAll(classid, PETSC_TRUE));
1140   PetscFunctionReturn(PETSC_SUCCESS);
1141 }
1142 
1143 /*@
1144   PetscLogEventExcludeClass - Deactivates event logging for a PETSc object class in every stage.
1145 
1146   Not Collective
1147 
1148   Input Parameter:
1149 . classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1150 
1151   Level: developer
1152 
1153   Note:
1154   If a class is excluded then events associated with that class are not logged.
1155 
1156 .seealso: [](ch_profiling), `PetscLogEventDeactivateClass()`, `PetscLogEventActivateClass()`, `PetscLogEventDeactivate()`, `PetscLogEventActivate()`
1157 @*/
1158 PetscErrorCode PetscLogEventExcludeClass(PetscClassId classid)
1159 {
1160   PetscFunctionBegin;
1161   PetscCall(PetscLogClassSetActiveAll(classid, PETSC_FALSE));
1162   PetscFunctionReturn(PETSC_SUCCESS);
1163 }
1164 
1165 /*
1166   PetscLogEventSetActive - Activate or inactivate logging for an event in a given stage
1167 
1168   Not Collective
1169 
1170   Input Parameters:
1171 + stage - A registered `PetscLogStage` (or `PETSC_DEFAULT` for the current stage)
1172 . event - A `PetscLogEvent`
1173 - isActive - If `PETSC_FALSE`, activity from this event (`PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogEventSync()`) will not be sent to log handlers during this stage
1174 
1175   Usage:
1176 .vb
1177       PetscLogEventSetActive(VEC_SetValues, PETSC_FALSE);
1178         [code where you do not want to log VecSetValues()]
1179       PetscLogEventSetActive(VEC_SetValues, PETSC_TRUE);
1180         [code where you do want to log VecSetValues()]
1181 .ve
1182 
1183   Level: advanced
1184 
1185   Note:
1186   The event may be either a pre-defined PETSc event (found in include/petsclog.h)
1187   or an event number obtained with `PetscLogEventRegister()`.
1188 
1189 .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1190 */
1191 static PetscErrorCode PetscLogEventSetActive(PetscLogStage stage, PetscLogEvent event, PetscBool isActive)
1192 {
1193   PetscLogState state;
1194 
1195   PetscFunctionBegin;
1196   PetscCall(PetscLogGetState(&state));
1197   if (state) PetscCall(PetscLogStateEventSetActive(state, stage, event, isActive));
1198   PetscFunctionReturn(PETSC_SUCCESS);
1199 }
1200 
1201 /*@
1202   PetscLogEventActivate - Indicates that a particular event should be logged.
1203 
1204   Not Collective
1205 
1206   Input Parameter:
1207 . event - The event id
1208 
1209   Example Usage:
1210 .vb
1211       PetscLogEventDeactivate(VEC_SetValues);
1212         [code where you do not want to log VecSetValues()]
1213       PetscLogEventActivate(VEC_SetValues);
1214         [code where you do want to log VecSetValues()]
1215 .ve
1216 
1217   Level: advanced
1218 
1219   Note:
1220   The event may be either a pre-defined PETSc event (found in include/petsclog.h)
1221   or an event number obtained with `PetscLogEventRegister()`.
1222 
1223 .seealso: [](ch_profiling), `PetscLogEventDeactivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1224 @*/
1225 PetscErrorCode PetscLogEventActivate(PetscLogEvent event)
1226 {
1227   PetscFunctionBegin;
1228   PetscCall(PetscLogEventSetActive(PETSC_DEFAULT, event, PETSC_TRUE));
1229   PetscFunctionReturn(PETSC_SUCCESS);
1230 }
1231 
1232 /*@
1233   PetscLogEventDeactivate - Indicates that a particular event should not be logged.
1234 
1235   Not Collective
1236 
1237   Input Parameter:
1238 . event - The event id
1239 
1240   Example Usage:
1241 .vb
1242       PetscLogEventDeactivate(VEC_SetValues);
1243         [code where you do not want to log VecSetValues()]
1244       PetscLogEventActivate(VEC_SetValues);
1245         [code where you do want to log VecSetValues()]
1246 .ve
1247 
1248   Level: advanced
1249 
1250   Note:
1251   The event may be either a pre-defined PETSc event (found in
1252   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).
1253 
1254 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1255 @*/
1256 PetscErrorCode PetscLogEventDeactivate(PetscLogEvent event)
1257 {
1258   PetscFunctionBegin;
1259   PetscCall(PetscLogEventSetActive(PETSC_DEFAULT, event, PETSC_FALSE));
1260   PetscFunctionReturn(PETSC_SUCCESS);
1261 }
1262 
1263 /*@
1264   PetscLogEventDeactivatePush - Indicates that a particular event should not be logged until `PetscLogEventDeactivatePop()` is called
1265 
1266   Not Collective
1267 
1268   Input Parameter:
1269 . event - The event id
1270 
1271   Example Usage:
1272 .vb
1273       PetscLogEventDeactivatePush(VEC_SetValues);
1274         [code where you do not want to log VecSetValues()]
1275       PetscLogEventDeactivatePop(VEC_SetValues);
1276         [code where you do want to log VecSetValues()]
1277 .ve
1278 
1279   Level: advanced
1280 
1281   Note:
1282   The event may be either a pre-defined PETSc event (found in
1283   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).
1284 
1285   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.
1286 
1287 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivate()`, `PetscLogEventDeactivatePop()`
1288 @*/
1289 PetscErrorCode PetscLogEventDeactivatePush(PetscLogEvent event)
1290 {
1291   PetscFunctionBegin;
1292   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1293     PetscLogHandler h = PetscLogHandlers[i].handler;
1294 
1295     if (h) PetscCall(PetscLogHandlerEventDeactivatePush(h, PETSC_DEFAULT, event));
1296   }
1297   PetscFunctionReturn(PETSC_SUCCESS);
1298 }
1299 
1300 /*@
1301   PetscLogEventDeactivatePop - Indicates that a particular event should again be logged after the logging was turned off with `PetscLogEventDeactivatePush()`
1302 
1303   Not Collective
1304 
1305   Input Parameter:
1306 . event - The event id
1307 
1308   Example Usage:
1309 .vb
1310       PetscLogEventDeactivatePush(VEC_SetValues);
1311         [code where you do not want to log VecSetValues()]
1312       PetscLogEventDeactivatePop(VEC_SetValues);
1313         [code where you do want to log VecSetValues()]
1314 .ve
1315 
1316   Level: advanced
1317 
1318   Note:
1319   The event may be either a pre-defined PETSc event (found in
1320   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).
1321 
1322 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`
1323 @*/
1324 PetscErrorCode PetscLogEventDeactivatePop(PetscLogEvent event)
1325 {
1326   PetscFunctionBegin;
1327   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1328     PetscLogHandler h = PetscLogHandlers[i].handler;
1329 
1330     if (h) PetscCall(PetscLogHandlerEventDeactivatePop(h, PETSC_DEFAULT, event));
1331   }
1332   PetscFunctionReturn(PETSC_SUCCESS);
1333 }
1334 
1335 /*@
1336   PetscLogEventSetActiveAll - Turns on logging of all events
1337 
1338   Not Collective
1339 
1340   Input Parameters:
1341 + event    - The event id
1342 - isActive - The activity flag determining whether the event is logged
1343 
1344   Level: advanced
1345 
1346 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1347 @*/
1348 PetscErrorCode PetscLogEventSetActiveAll(PetscLogEvent event, PetscBool isActive)
1349 {
1350   PetscLogState state;
1351 
1352   PetscFunctionBegin;
1353   PetscCall(PetscLogGetState(&state));
1354   if (state) PetscCall(PetscLogStateEventSetActiveAll(state, event, isActive));
1355   PetscFunctionReturn(PETSC_SUCCESS);
1356 }
1357 
1358 /*
1359   PetscLogClassSetActive - Activates event logging for a PETSc object class for the current stage
1360 
1361   Not Collective
1362 
1363   Input Parameters:
1364 + stage - A registered `PetscLogStage` (or `PETSC_DEFAULT` for the current stage)
1365 . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1366 - isActive - If `PETSC_FALSE`, events associated with this class are not sent to log handlers.
1367 
1368   Level: developer
1369 
1370 .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`
1371 */
1372 static PetscErrorCode PetscLogClassSetActive(PetscLogStage stage, PetscClassId classid, PetscBool isActive)
1373 {
1374   PetscLogState state;
1375 
1376   PetscFunctionBegin;
1377   PetscCall(PetscLogGetState(&state));
1378   if (state) PetscCall(PetscLogStateClassSetActive(state, stage, classid, isActive));
1379   PetscFunctionReturn(PETSC_SUCCESS);
1380 }
1381 
1382 /*@
1383   PetscLogEventActivateClass - Activates event logging for a PETSc object class for the current stage
1384 
1385   Not Collective
1386 
1387   Input Parameter:
1388 . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1389 
1390   Level: developer
1391 
1392 .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1393 @*/
1394 PetscErrorCode PetscLogEventActivateClass(PetscClassId classid)
1395 {
1396   PetscFunctionBegin;
1397   PetscCall(PetscLogClassSetActive(PETSC_DEFAULT, classid, PETSC_TRUE));
1398   PetscFunctionReturn(PETSC_SUCCESS);
1399 }
1400 
1401 /*@
1402   PetscLogEventDeactivateClass - Deactivates event logging for a PETSc object class for the current stage
1403 
1404   Not Collective
1405 
1406   Input Parameter:
1407 . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1408 
1409   Level: developer
1410 
1411 .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventActivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1412 @*/
1413 PetscErrorCode PetscLogEventDeactivateClass(PetscClassId classid)
1414 {
1415   PetscFunctionBegin;
1416   PetscCall(PetscLogClassSetActive(PETSC_DEFAULT, classid, PETSC_FALSE));
1417   PetscFunctionReturn(PETSC_SUCCESS);
1418 }
1419 
1420 /*MC
1421   PetscLogEventSync - Synchronizes the beginning of a user event.
1422 
1423   Synopsis:
1424   #include <petsclog.h>
1425   PetscErrorCode PetscLogEventSync(PetscLogEvent e, MPI_Comm comm)
1426 
1427   Collective
1428 
1429   Input Parameters:
1430 + e    - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1431 - comm - an MPI communicator
1432 
1433   Example Usage:
1434 .vb
1435   PetscLogEvent USER_EVENT;
1436 
1437   PetscLogEventRegister("User event", 0, &USER_EVENT);
1438   PetscLogEventSync(USER_EVENT, PETSC_COMM_WORLD);
1439   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1440   [code segment to monitor]
1441   PetscLogEventEnd(USER_EVENT, 0, 0, 0 , 0);
1442 .ve
1443 
1444   Level: developer
1445 
1446   Note:
1447   This routine should be called only if there is not a `PetscObject` available to pass to
1448   `PetscLogEventBegin()`.
1449 
1450 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`
1451 M*/
1452 
1453 /*MC
1454   PetscLogEventBegin - Logs the beginning of a user event.
1455 
1456   Synopsis:
1457   #include <petsclog.h>
1458   PetscErrorCode PetscLogEventBegin(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
1459 
1460   Not Collective
1461 
1462   Input Parameters:
1463 + e  - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1464 . o1 - object associated with the event, or `NULL`
1465 . o2 - object associated with the event, or `NULL`
1466 . o3 - object associated with the event, or `NULL`
1467 - o4 - object associated with the event, or `NULL`
1468 
1469   Fortran Synopsis:
1470   void PetscLogEventBegin(int e, PetscErrorCode ierr)
1471 
1472   Example Usage:
1473 .vb
1474   PetscLogEvent USER_EVENT;
1475 
1476   PetscLogDouble user_event_flops;
1477   PetscLogEventRegister("User event",0, &USER_EVENT);
1478   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1479   [code segment to monitor]
1480   PetscLogFlops(user_event_flops);
1481   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
1482 .ve
1483 
1484   Level: intermediate
1485 
1486   Developer Note:
1487   `PetscLogEventBegin()` and `PetscLogEventBegin()` return error codes instead of explicitly
1488   handling the errors that occur in the macro directly because other packages that use this
1489   macros have used them in their own functions or methods that do not return error codes and it
1490   would be disruptive to change the current behavior.
1491 
1492 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventEnd()`, `PetscLogFlops()`
1493 M*/
1494 
1495 /*MC
1496   PetscLogEventEnd - Log the end of a user event.
1497 
1498   Synopsis:
1499   #include <petsclog.h>
1500   PetscErrorCode PetscLogEventEnd(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
1501 
1502   Not Collective
1503 
1504   Input Parameters:
1505 + e  - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1506 . o1 - object associated with the event, or `NULL`
1507 . o2 - object associated with the event, or `NULL`
1508 . o3 - object associated with the event, or `NULL`
1509 - o4 - object associated with the event, or `NULL`
1510 
1511   Fortran Synopsis:
1512   void PetscLogEventEnd(int e, PetscErrorCode ierr)
1513 
1514   Example Usage:
1515 .vb
1516   PetscLogEvent USER_EVENT;
1517 
1518   PetscLogDouble user_event_flops;
1519   PetscLogEventRegister("User event", 0, &USER_EVENT);
1520   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1521   [code segment to monitor]
1522   PetscLogFlops(user_event_flops);
1523   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
1524 .ve
1525 
1526   Level: intermediate
1527 
1528 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogFlops()`
1529 M*/
1530 
1531 /*@C
1532   PetscLogStageGetPerfInfo - Return the performance information about the given stage
1533 
1534   No Fortran Support
1535 
1536   Input Parameters:
1537 . stage - The stage number or `PETSC_DETERMINE` for the current stage
1538 
1539   Output Parameter:
1540 . info - This structure is filled with the performance information
1541 
1542   Level: intermediate
1543 
1544   Notes:
1545   This is a low level routine used by the logging functions in PETSc.
1546 
1547   A `PETSCLOGHANDLERDEFAULT` must be running for this to work, having been started either with
1548   `PetscLogDefaultBegin()` or from the command line with `-log_view`.  If it was not started,
1549   all performance statistics in `info` will be zeroed.
1550 
1551 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogGetDefaultHandler()`
1552 @*/
1553 PetscErrorCode PetscLogStageGetPerfInfo(PetscLogStage stage, PetscEventPerfInfo *info)
1554 {
1555   PetscLogHandler     handler;
1556   PetscEventPerfInfo *event_info;
1557 
1558   PetscFunctionBegin;
1559   PetscAssertPointer(info, 2);
1560   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1561   if (handler) {
1562     PetscCall(PetscLogHandlerGetStagePerfInfo(handler, stage, &event_info));
1563     *info = *event_info;
1564   } else {
1565     PetscCall(PetscInfo(NULL, "Default log handler is not running, PetscLogStageGetPerfInfo() returning zeros\n"));
1566     PetscCall(PetscMemzero(info, sizeof(*info)));
1567   }
1568   PetscFunctionReturn(PETSC_SUCCESS);
1569 }
1570 
1571 /*@C
1572   PetscLogEventGetPerfInfo - Return the performance information about the given event in the given stage
1573 
1574   No Fortran Support
1575 
1576   Input Parameters:
1577 + stage - The stage number or `PETSC_DETERMINE` for the current stage
1578 - event - The event number
1579 
1580   Output Parameter:
1581 . info - This structure is filled with the performance information
1582 
1583   Level: intermediate
1584 
1585   Note:
1586   This is a low level routine used by the logging functions in PETSc
1587 
1588   A `PETSCLOGHANDLERDEFAULT` must be running for this to work, having been started either with
1589   `PetscLogDefaultBegin()` or from the command line with `-log_view`.  If it was not started,
1590   all performance statistics in `info` will be zeroed.
1591 
1592 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogGetDefaultHandler()`
1593 @*/
1594 PetscErrorCode PetscLogEventGetPerfInfo(PetscLogStage stage, PetscLogEvent event, PetscEventPerfInfo *info)
1595 {
1596   PetscLogHandler     handler;
1597   PetscEventPerfInfo *event_info;
1598 
1599   PetscFunctionBegin;
1600   PetscAssertPointer(info, 3);
1601   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1602   if (handler) {
1603     PetscCall(PetscLogHandlerGetEventPerfInfo(handler, stage, event, &event_info));
1604     *info = *event_info;
1605   } else {
1606     PetscCall(PetscInfo(NULL, "Default log handler is not running, PetscLogEventGetPerfInfo() returning zeros\n"));
1607     PetscCall(PetscMemzero(info, sizeof(*info)));
1608   }
1609   PetscFunctionReturn(PETSC_SUCCESS);
1610 }
1611 
1612 /*@
1613   PetscLogEventSetDof - Set the nth number of degrees of freedom of a numerical problem associated with this event
1614 
1615   Not Collective
1616 
1617   Input Parameters:
1618 + event - The event id to log
1619 . n     - The dof index, in [0, 8)
1620 - dof   - The number of dofs
1621 
1622   Options Database Key:
1623 . -log_view - Activates log summary
1624 
1625   Level: developer
1626 
1627   Note:
1628   This is to enable logging of convergence
1629 
1630 .seealso: `PetscLogEventSetError()`, `PetscLogEventRegister()`, `PetscLogGetDefaultHandler()`
1631 @*/
1632 PetscErrorCode PetscLogEventSetDof(PetscLogEvent event, PetscInt n, PetscLogDouble dof)
1633 {
1634   PetscFunctionBegin;
1635   PetscCheck(!(n < 0) && !(n > 7), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Error index %" PetscInt_FMT " is not in [0, 8)", n);
1636   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1637     PetscLogHandler h = PetscLogHandlers[i].handler;
1638 
1639     if (h) {
1640       PetscEventPerfInfo *event_info;
1641 
1642       PetscCall(PetscLogHandlerGetEventPerfInfo(h, PETSC_DEFAULT, event, &event_info));
1643       if (event_info) event_info->dof[n] = dof;
1644     }
1645   }
1646   PetscFunctionReturn(PETSC_SUCCESS);
1647 }
1648 
1649 /*@
1650   PetscLogEventSetError - Set the nth error associated with a numerical problem associated with this event
1651 
1652   Not Collective
1653 
1654   Input Parameters:
1655 + event - The event id to log
1656 . n     - The error index, in [0, 8)
1657 - error - The error
1658 
1659   Options Database Key:
1660 . -log_view - Activates log summary
1661 
1662   Level: developer
1663 
1664   Notes:
1665   This is to enable logging of convergence, and enable users to interpret the errors as they wish. For example,
1666   as different norms, or as errors for different fields
1667 
1668   This is a low level routine used by the logging functions in PETSc
1669 
1670 .seealso: `PetscLogEventSetDof()`, `PetscLogEventRegister()`, `PetscLogGetDefaultHandler()`
1671 @*/
1672 PetscErrorCode PetscLogEventSetError(PetscLogEvent event, PetscInt n, PetscLogDouble error)
1673 {
1674   PetscFunctionBegin;
1675   PetscCheck(!(n < 0) && !(n > 7), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Error index %" PetscInt_FMT " is not in [0, 8)", n);
1676   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1677     PetscLogHandler h = PetscLogHandlers[i].handler;
1678 
1679     if (h) {
1680       PetscEventPerfInfo *event_info;
1681 
1682       PetscCall(PetscLogHandlerGetEventPerfInfo(h, PETSC_DEFAULT, event, &event_info));
1683       if (event_info) event_info->errors[n] = error;
1684     }
1685   }
1686   PetscFunctionReturn(PETSC_SUCCESS);
1687 }
1688 
1689 /*@
1690   PetscLogEventGetId - Returns the event id when given the event name.
1691 
1692   Not Collective
1693 
1694   Input Parameter:
1695 . name - The event name
1696 
1697   Output Parameter:
1698 . event - The event, or -1 if no event with that name exists
1699 
1700   Level: intermediate
1701 
1702 .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1703 @*/
1704 PetscErrorCode PetscLogEventGetId(const char name[], PetscLogEvent *event)
1705 {
1706   PetscLogState state;
1707 
1708   PetscFunctionBegin;
1709   *event = -1;
1710   PetscCall(PetscLogGetState(&state));
1711   if (state) PetscCall(PetscLogStateGetEventFromName(state, name, event));
1712   PetscFunctionReturn(PETSC_SUCCESS);
1713 }
1714 
1715 /*@
1716   PetscLogEventGetName - Returns the event name when given the event id.
1717 
1718   Not Collective
1719 
1720   Input Parameter:
1721 . event - The event
1722 
1723   Output Parameter:
1724 . name - The event name
1725 
1726   Level: intermediate
1727 
1728 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
1729 @*/
1730 PetscErrorCode PetscLogEventGetName(PetscLogEvent event, const char *name[])
1731 {
1732   PetscLogEventInfo event_info;
1733   PetscLogState     state;
1734 
1735   PetscFunctionBegin;
1736   *name = NULL;
1737   PetscCall(PetscLogGetState(&state));
1738   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
1739   PetscCall(PetscLogStateEventGetInfo(state, event, &event_info));
1740   *name = event_info.name;
1741   PetscFunctionReturn(PETSC_SUCCESS);
1742 }
1743 
1744 /*@
1745   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.
1746 
1747   Not collective
1748 
1749   Level: advanced
1750 
1751   Notes:
1752   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()`).
1753 
1754   Other log handlers (such as the nested handler, `PetscLogNestedBegin()`) will ignore this function.
1755 
1756 .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsResume()`, `PetscLogGetDefaultHandler()`
1757 @*/
1758 PetscErrorCode PetscLogEventsPause(void)
1759 {
1760   PetscFunctionBegin;
1761   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1762     PetscLogHandler h = PetscLogHandlers[i].handler;
1763 
1764     if (h) PetscCall(PetscLogHandlerEventsPause(h));
1765   }
1766   PetscFunctionReturn(PETSC_SUCCESS);
1767 }
1768 
1769 /*@
1770   PetscLogEventsResume - Return logging to normal behavior after it was paused with `PetscLogEventsPause()`.
1771 
1772   Not collective
1773 
1774   Level: advanced
1775 
1776 .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsPause()`, `PetscLogGetDefaultHandler()`
1777 @*/
1778 PetscErrorCode PetscLogEventsResume(void)
1779 {
1780   PetscFunctionBegin;
1781   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1782     PetscLogHandler h = PetscLogHandlers[i].handler;
1783 
1784     if (h) PetscCall(PetscLogHandlerEventsResume(h));
1785   }
1786   PetscFunctionReturn(PETSC_SUCCESS);
1787 }
1788 
1789 /*------------------------------------------------ Class Functions --------------------------------------------------*/
1790 
1791 /*MC
1792    PetscLogObjectCreate - Log the creation of a `PetscObject`
1793 
1794    Synopsis:
1795    #include <petsclog.h>
1796    PetscErrorCode PetscLogObjectCreate(PetscObject h)
1797 
1798    Not Collective
1799 
1800    Input Parameters:
1801 .  h - A `PetscObject`
1802 
1803    Level: developer
1804 
1805    Developer Note:
1806      Called internally by PETSc when creating objects: users do not need to call this directly.
1807      Notification of the object creation is sent to each `PetscLogHandler` that is running.
1808 
1809 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectDestroy()`
1810 M*/
1811 
1812 /*MC
1813    PetscLogObjectDestroy - Logs the destruction of a `PetscObject`
1814 
1815    Synopsis:
1816    #include <petsclog.h>
1817    PetscErrorCode PetscLogObjectDestroy(PetscObject h)
1818 
1819    Not Collective
1820 
1821    Input Parameters:
1822 .  h - A `PetscObject`
1823 
1824    Level: developer
1825 
1826    Developer Note:
1827      Called internally by PETSc when destroying objects: users do not need to call this directly.
1828      Notification of the object creation is sent to each `PetscLogHandler` that is running.
1829 
1830 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectCreate()`
1831 M*/
1832 
1833 /*@
1834   PetscLogClassGetClassId - Returns the `PetscClassId` when given the class name.
1835 
1836   Not Collective
1837 
1838   Input Parameter:
1839 . name - The class name
1840 
1841   Output Parameter:
1842 . classid - The `PetscClassId` id, or -1 if no class with that name exists
1843 
1844   Level: intermediate
1845 
1846 .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1847 @*/
1848 PetscErrorCode PetscLogClassGetClassId(const char name[], PetscClassId *classid)
1849 {
1850   PetscLogClass     log_class;
1851   PetscLogClassInfo class_info;
1852   PetscLogState     state;
1853 
1854   PetscFunctionBegin;
1855   *classid = -1;
1856   PetscCall(PetscLogGetState(&state));
1857   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
1858   PetscCall(PetscLogStateGetClassFromName(state, name, &log_class));
1859   if (log_class < 0) {
1860     *classid = -1;
1861     PetscFunctionReturn(PETSC_SUCCESS);
1862   }
1863   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
1864   *classid = class_info.classid;
1865   PetscFunctionReturn(PETSC_SUCCESS);
1866 }
1867 
1868 /*@C
1869   PetscLogClassIdGetName - Returns a `PetscClassId`'s name.
1870 
1871   Not Collective
1872 
1873   Input Parameter:
1874 . classid - A `PetscClassId`
1875 
1876   Output Parameter:
1877 . name - The class name
1878 
1879   Level: intermediate
1880 
1881 .seealso: [](ch_profiling), `PetscLogClassRegister()`, `PetscLogClassBegin()`, `PetscLogClassEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadClass()`
1882 @*/
1883 PetscErrorCode PetscLogClassIdGetName(PetscClassId classid, const char **name)
1884 {
1885   PetscLogClass     log_class;
1886   PetscLogClassInfo class_info;
1887   PetscLogState     state;
1888 
1889   PetscFunctionBegin;
1890   PetscCall(PetscLogGetState(&state));
1891   PetscCall(PetscLogStateGetClassFromClassId(state, classid, &log_class));
1892   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
1893   *name = class_info.name;
1894   PetscFunctionReturn(PETSC_SUCCESS);
1895 }
1896 
1897 /*------------------------------------------------ Output Functions -------------------------------------------------*/
1898 /*@
1899   PetscLogDump - Dumps logs of objects to a file. This file is intended to
1900   be read by bin/petscview. This program no longer exists.
1901 
1902   Collective on `PETSC_COMM_WORLD`
1903 
1904   Input Parameter:
1905 . sname - an optional file name
1906 
1907   Example Usage:
1908 .vb
1909   PetscInitialize(...);
1910   PetscLogDefaultBegin();
1911   // ... code ...
1912   PetscLogDump(filename);
1913   PetscFinalize();
1914 .ve
1915 
1916   Level: advanced
1917 
1918   Note:
1919   The default file name is Log.<rank> where <rank> is the MPI process rank. If no name is specified,
1920   this file will be used.
1921 
1922 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
1923 @*/
1924 PetscErrorCode PetscLogDump(const char sname[])
1925 {
1926   PetscLogHandler handler;
1927 
1928   PetscFunctionBegin;
1929   PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1930   PetscCall(PetscLogHandlerDump(handler, sname));
1931   PetscFunctionReturn(PETSC_SUCCESS);
1932 }
1933 
1934 /*@
1935   PetscLogMPEDump - Dumps the MPE logging info to file for later use with Jumpshot.
1936 
1937   Collective on `PETSC_COMM_WORLD`
1938 
1939   Input Parameter:
1940 . sname - filename for the MPE logfile
1941 
1942   Level: advanced
1943 
1944 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogMPEBegin()`
1945 @*/
1946 PetscErrorCode PetscLogMPEDump(const char sname[])
1947 {
1948   PetscFunctionBegin;
1949   #if defined(PETSC_HAVE_MPE)
1950   if (PetscBeganMPE) {
1951     char name[PETSC_MAX_PATH_LEN];
1952 
1953     PetscCall(PetscInfo(0, "Finalizing MPE.\n"));
1954     if (sname) {
1955       PetscCall(PetscStrncpy(name, sname, sizeof(name)));
1956     } else {
1957       PetscCall(PetscGetProgramName(name, sizeof(name)));
1958     }
1959     PetscCall(MPE_Finish_log(name));
1960   } else {
1961     PetscCall(PetscInfo(0, "Not finalizing MPE (not started by PETSc).\n"));
1962   }
1963   #else
1964   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
1965   #endif
1966   PetscFunctionReturn(PETSC_SUCCESS);
1967 }
1968 
1969 /*@
1970   PetscLogView - Prints a summary of the logging.
1971 
1972   Collective
1973 
1974   Input Parameter:
1975 . viewer - an ASCII viewer
1976 
1977   Options Database Keys:
1978 + -log_view [:filename]                    - Prints summary of log information
1979 . -log_view :filename.py:ascii_info_detail - Saves logging information from each process as a Python file
1980 . -log_view :filename.xml:ascii_xml        - Saves a summary of the logging information in a nested format (see below for how to view it)
1981 . -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)
1982 . -log_view_memory                         - Also display memory usage in each event
1983 . -log_view_gpu_time                       - Also display time in each event for GPU kernels (Note this may slow the computation)
1984 . -log_all                                 - Saves a file Log.rank for each MPI rank with details of each step of the computation
1985 - -log_trace [filename]                    - Displays a trace of what each process is doing
1986 
1987   Level: beginner
1988 
1989   Notes:
1990   It is possible to control the logging programmatically but we recommend using the options database approach whenever possible
1991   By default the summary is printed to stdout.
1992 
1993   Before calling this routine you must have called either PetscLogDefaultBegin() or PetscLogNestedBegin()
1994 
1995   If PETSc is configured with --with-logging=0 then this functionality is not available
1996 
1997   To view the nested XML format filename.xml first copy  ${PETSC_DIR}/share/petsc/xml/performance_xml2html.xsl to the current
1998   directory then open filename.xml with your browser. Specific notes for certain browsers
1999 .vb
2000     Firefox and Internet explorer - simply open the file
2001     Google Chrome - you must start up Chrome with the option --allow-file-access-from-files
2002     Safari - see https://ccm.net/faq/36342-safari-how-to-enable-local-file-access
2003 .ve
2004   or one can use the package <http://xmlsoft.org/XSLT/xsltproc2.html> to translate the xml file to html and then open it with
2005   your browser.
2006   Alternatively, use the script ${PETSC_DIR}/lib/petsc/bin/petsc-performance-view to automatically open a new browser
2007   window and render the XML log file contents.
2008 
2009   The nested XML format was kindly donated by Koos Huijssen and Christiaan M. Klaij  MARITIME  RESEARCH  INSTITUTE  NETHERLANDS
2010 
2011   The Flame Graph output can be visualised using either the original Flame Graph script <https://github.com/brendangregg/FlameGraph>
2012   or using speedscope <https://www.speedscope.app>.
2013   Old XML profiles may be converted into this format using the script ${PETSC_DIR}/lib/petsc/bin/xml2flamegraph.py.
2014 
2015 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogDump()`
2016 @*/
2017 PetscErrorCode PetscLogView(PetscViewer viewer)
2018 {
2019   PetscBool         isascii;
2020   PetscViewerFormat format;
2021   int               stage;
2022   PetscLogState     state;
2023   PetscIntStack     temp_stack;
2024   PetscLogHandler   handler;
2025   PetscBool         is_empty;
2026 
2027   PetscFunctionBegin;
2028   PetscCall(PetscLogGetState(&state));
2029   /* Pop off any stages the user forgot to remove */
2030   PetscCall(PetscIntStackCreate(&temp_stack));
2031   PetscCall(PetscLogStateGetCurrentStage(state, &stage));
2032   while (stage >= 0) {
2033     PetscCall(PetscLogStagePop());
2034     PetscCall(PetscIntStackPush(temp_stack, stage));
2035     PetscCall(PetscLogStateGetCurrentStage(state, &stage));
2036   }
2037   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2038   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Currently can only view logging to ASCII");
2039   PetscCall(PetscViewerGetFormat(viewer, &format));
2040   if (format == PETSC_VIEWER_ASCII_XML || format == PETSC_VIEWER_ASCII_FLAMEGRAPH) {
2041     PetscCall(PetscLogGetHandler(PETSCLOGHANDLERNESTED, &handler));
2042     PetscCall(PetscLogHandlerView(handler, viewer));
2043   } else {
2044     PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
2045     PetscCall(PetscLogHandlerView(handler, viewer));
2046   }
2047   PetscCall(PetscIntStackEmpty(temp_stack, &is_empty));
2048   while (!is_empty) {
2049     PetscCall(PetscIntStackPop(temp_stack, &stage));
2050     PetscCall(PetscLogStagePush(stage));
2051     PetscCall(PetscIntStackEmpty(temp_stack, &is_empty));
2052   }
2053   PetscCall(PetscIntStackDestroy(temp_stack));
2054   PetscFunctionReturn(PETSC_SUCCESS);
2055 }
2056 
2057 /*@C
2058   PetscLogViewFromOptions - Processes command line options to determine if/how a `PetscLog` is to be viewed.
2059 
2060   Collective on `PETSC_COMM_WORLD`
2061 
2062   Level: developer
2063 
2064 .seealso: [](ch_profiling), `PetscLogView()`
2065 @*/
2066 PetscErrorCode PetscLogViewFromOptions(void)
2067 {
2068   PetscInt          n_max = PETSC_LOG_VIEW_FROM_OPTIONS_MAX;
2069   PetscViewer       viewers[PETSC_LOG_VIEW_FROM_OPTIONS_MAX];
2070   PetscViewerFormat formats[PETSC_LOG_VIEW_FROM_OPTIONS_MAX];
2071   PetscBool         flg;
2072 
2073   PetscFunctionBegin;
2074   PetscCall(PetscOptionsCreateViewers(PETSC_COMM_WORLD, NULL, NULL, "-log_view", &n_max, viewers, formats, &flg));
2075   /*
2076      PetscLogHandlerView_Default_Info() wants to be sure that the only objects still around are these viewers, so keep track of how many there are
2077    */
2078   PetscLogNumViewersCreated = n_max;
2079   for (PetscInt i = 0; i < n_max; i++) {
2080     PetscInt refct;
2081 
2082     PetscCall(PetscViewerPushFormat(viewers[i], formats[i]));
2083     PetscCall(PetscLogView(viewers[i]));
2084     PetscCall(PetscViewerPopFormat(viewers[i]));
2085     PetscCall(PetscObjectGetReference((PetscObject)viewers[i], &refct));
2086     PetscCall(PetscViewerDestroy(&viewers[i]));
2087     if (refct == 1) PetscLogNumViewersDestroyed++;
2088   }
2089   PetscLogNumViewersDestroyed = 0;
2090   PetscFunctionReturn(PETSC_SUCCESS);
2091 }
2092 
2093 PETSC_INTERN PetscErrorCode PetscLogHandlerNestedSetThreshold(PetscLogHandler, PetscLogDouble, PetscLogDouble *);
2094 
2095 /*@
2096   PetscLogSetThreshold - Set the threshold time for logging the events; this is a percentage out of 100, so 1. means any event
2097   that takes 1 or more percent of the time.
2098 
2099   Logically Collective on `PETSC_COMM_WORLD`
2100 
2101   Input Parameter:
2102 . newThresh - the threshold to use
2103 
2104   Output Parameter:
2105 . oldThresh - the previously set threshold value
2106 
2107   Options Database Keys:
2108 . -log_view :filename.xml:ascii_xml - Prints an XML summary of flop and timing information to the file
2109 
2110   Example Usage:
2111 .vb
2112   PetscInitialize(...);
2113   PetscLogNestedBegin();
2114   PetscLogSetThreshold(0.1,&oldthresh);
2115   // ... code ...
2116   PetscLogView(viewer);
2117   PetscFinalize();
2118 .ve
2119 
2120   Level: advanced
2121 
2122   Note:
2123   This threshold is only used by the nested log handler
2124 
2125 .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`,
2126           `PetscLogNestedBegin()`
2127 @*/
2128 PetscErrorCode PetscLogSetThreshold(PetscLogDouble newThresh, PetscLogDouble *oldThresh)
2129 {
2130   PetscLogHandler handler;
2131 
2132   PetscFunctionBegin;
2133   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERNESTED, &handler));
2134   PetscCall(PetscLogHandlerNestedSetThreshold(handler, newThresh, oldThresh));
2135   PetscFunctionReturn(PETSC_SUCCESS);
2136 }
2137 
2138 /*----------------------------------------------- Counter Functions -------------------------------------------------*/
2139 /*@
2140   PetscGetFlops - Returns the number of flops used on this processor
2141   since the program began.
2142 
2143   Not Collective
2144 
2145   Output Parameter:
2146 . flops - number of floating point operations
2147 
2148   Level: intermediate
2149 
2150   Notes:
2151   A global counter logs all PETSc flop counts.  The user can use
2152   `PetscLogFlops()` to increment this counter to include flops for the
2153   application code.
2154 
2155   A separate counter `PetscLogGpuFlops()` logs the flops that occur on any GPU associated with this MPI rank
2156 
2157 .seealso: [](ch_profiling), `PetscLogGpuFlops()`, `PetscTime()`, `PetscLogFlops()`
2158 @*/
2159 PetscErrorCode PetscGetFlops(PetscLogDouble *flops)
2160 {
2161   PetscFunctionBegin;
2162   *flops = petsc_TotalFlops;
2163   PetscFunctionReturn(PETSC_SUCCESS);
2164 }
2165 
2166 /*@C
2167   PetscLogObjectState - Record information about an object with the default log handler
2168 
2169   Not Collective
2170 
2171   Input Parameters:
2172 + obj    - the `PetscObject`
2173 . format - a printf-style format string
2174 - ...    - printf arguments to format
2175 
2176   Level: developer
2177 
2178 .seealso: [](ch_profiling), `PetscLogObjectCreate()`, `PetscLogObjectDestroy()`, `PetscLogGetDefaultHandler()`
2179 @*/
2180 PetscErrorCode PetscLogObjectState(PetscObject obj, const char format[], ...)
2181 {
2182   PetscFunctionBegin;
2183   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
2184     PetscLogHandler h = PetscLogHandlers[i].handler;
2185 
2186     if (h) {
2187       va_list Argp;
2188       va_start(Argp, format);
2189       PetscCall(PetscLogHandlerLogObjectState_Internal(h, obj, format, Argp));
2190       va_end(Argp);
2191     }
2192   }
2193   PetscFunctionReturn(PETSC_SUCCESS);
2194 }
2195 
2196 /*MC
2197   PetscLogFlops - Adds floating point operations to the global counter.
2198 
2199   Synopsis:
2200   #include <petsclog.h>
2201   PetscErrorCode PetscLogFlops(PetscLogDouble f)
2202 
2203   Not Collective
2204 
2205   Input Parameter:
2206 . f - flop counter
2207 
2208   Example Usage:
2209 .vb
2210   PetscLogEvent USER_EVENT;
2211 
2212   PetscLogEventRegister("User event", 0, &USER_EVENT);
2213   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
2214   [code segment to monitor]
2215   PetscLogFlops(user_flops)
2216   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
2217 .ve
2218 
2219   Level: intermediate
2220 
2221   Note:
2222    A global counter logs all PETSc flop counts. The user can use PetscLogFlops() to increment
2223    this counter to include flops for the application code.
2224 
2225 .seealso: [](ch_profiling), `PetscLogGpuFlops()`, `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscGetFlops()`
2226 M*/
2227 
2228 /*MC
2229   PetscPreLoadBegin - Begin a segment of code that may be preloaded (run twice) to get accurate
2230   timings
2231 
2232   Synopsis:
2233   #include <petsclog.h>
2234   void PetscPreLoadBegin(PetscBool flag, char *name);
2235 
2236   Not Collective
2237 
2238   Input Parameters:
2239 + flag - `PETSC_TRUE` to run twice, `PETSC_FALSE` to run once, may be overridden with command
2240          line option `-preload true|false`
2241 - name - name of first stage (lines of code timed separately with `-log_view`) to be preloaded
2242 
2243   Example Usage:
2244 .vb
2245   PetscPreLoadBegin(PETSC_TRUE, "first stage");
2246   // lines of code
2247   PetscPreLoadStage("second stage");
2248   // lines of code
2249   PetscPreLoadEnd();
2250 .ve
2251 
2252   Level: intermediate
2253 
2254   Note:
2255   Only works in C/C++, not Fortran
2256 
2257   Flags available within the macro\:
2258 + PetscPreLoadingUsed - `PETSC_TRUE` if we are or have done preloading
2259 . PetscPreLoadingOn   - `PETSC_TRUE` if it is CURRENTLY doing preload
2260 . PetscPreLoadIt      - `0` for the first computation (with preloading turned off it is only
2261                         `0`) `1`  for the second
2262 - PetscPreLoadMax     - number of times it will do the computation, only one when preloading is
2263                         turned on
2264 
2265   The first two variables are available throughout the program, the second two only between the
2266   `PetscPreLoadBegin()` and `PetscPreLoadEnd()`
2267 
2268 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
2269 M*/
2270 
2271 /*MC
2272   PetscPreLoadEnd - End a segment of code that may be preloaded (run twice) to get accurate
2273   timings
2274 
2275   Synopsis:
2276   #include <petsclog.h>
2277   void PetscPreLoadEnd(void);
2278 
2279   Not Collective
2280 
2281   Example Usage:
2282 .vb
2283   PetscPreLoadBegin(PETSC_TRUE, "first stage");
2284   // lines of code
2285   PetscPreLoadStage("second stage");
2286   // lines of code
2287   PetscPreLoadEnd();
2288 .ve
2289 
2290   Level: intermediate
2291 
2292   Note:
2293   Only works in C/C++ not Fortran
2294 
2295 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadStage()`
2296 M*/
2297 
2298 /*MC
2299   PetscPreLoadStage - Start a new segment of code to be timed separately to get accurate timings
2300 
2301   Synopsis:
2302   #include <petsclog.h>
2303   void PetscPreLoadStage(char *name);
2304 
2305   Not Collective
2306 
2307   Example Usage:
2308 .vb
2309   PetscPreLoadBegin(PETSC_TRUE,"first stage");
2310   // lines of code
2311   PetscPreLoadStage("second stage");
2312   // lines of code
2313   PetscPreLoadEnd();
2314 .ve
2315 
2316   Level: intermediate
2317 
2318   Note:
2319   Only works in C/C++ not Fortran
2320 
2321 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`
2322 M*/
2323 
2324   #if PetscDefined(HAVE_DEVICE)
2325     #include <petsc/private/deviceimpl.h>
2326 
2327 /*@
2328   PetscLogGpuTime - turn on the logging of GPU time for GPU kernels
2329 
2330   Options Database Key:
2331 . -log_view_gpu_time - provide the GPU times for all events in the `-log_view` output
2332 
2333   Level: advanced
2334 
2335   Notes:
2336   Turning on the timing of the GPU kernels can slow down the entire computation and should only
2337   be used when studying the performance of individual operations on GPU such as vector operations and
2338   matrix-vector operations.
2339 
2340   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
2341 
2342   This routine should only be called once near the beginning of the program. Once it is started
2343   it cannot be turned off.
2344 
2345 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTimeBegin()`
2346 @*/
2347 PetscErrorCode PetscLogGpuTime(void)
2348 {
2349   PetscFunctionBegin;
2350   PetscCheck(petsc_gtime == 0.0, PETSC_COMM_SELF, PETSC_ERR_SUP, "GPU logging has already been turned on");
2351   PetscLogGpuTimeFlag = PETSC_TRUE;
2352   PetscFunctionReturn(PETSC_SUCCESS);
2353 }
2354 
2355 /*@
2356   PetscLogGpuTimeBegin - Start timer for device
2357 
2358   Level: intermediate
2359 
2360   Notes:
2361   When GPU is enabled, the timer is run on the GPU, it is a separate logging of time
2362   devoted to GPU computations (excluding kernel launch times).
2363 
2364   When GPU is not available, the timer is run on the CPU, it is a separate logging of
2365   time devoted to GPU computations (including kernel launch times).
2366 
2367   There is no need to call WaitForCUDA() or WaitForHIP() between `PetscLogGpuTimeBegin()` and
2368   `PetscLogGpuTimeEnd()`
2369 
2370   This timer should NOT include times for data transfers between the GPU and CPU, nor setup
2371   actions such as allocating space.
2372 
2373   The regular logging captures the time for data transfers and any CPU activities during the
2374   event. It is used to compute the flop rate on the GPU as it is actively engaged in running a
2375   kernel.
2376 
2377   Developer Notes:
2378   The GPU event timer captures the execution time of all the kernels launched in the default
2379   stream by the CPU between `PetscLogGpuTimeBegin()` and `PetscLogGpuTimeEnd()`.
2380 
2381   `PetscLogGpuTimeBegin()` and `PetscLogGpuTimeEnd()` insert the begin and end events into the
2382   default stream (stream 0). The device will record a time stamp for the event when it reaches
2383   that event in the stream. The function xxxEventSynchronize() is called in
2384   `PetscLogGpuTimeEnd()` to block CPU execution, but not continued GPU execution, until the
2385   timer event is recorded.
2386 
2387 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTime()`
2388 @*/
2389 PetscErrorCode PetscLogGpuTimeBegin(void)
2390 {
2391   PetscBool isActive;
2392 
2393   PetscFunctionBegin;
2394   PetscCall(PetscLogEventBeginIsActive(&isActive));
2395   if (!isActive || !PetscLogGpuTimeFlag) PetscFunctionReturn(PETSC_SUCCESS);
2396     #if defined(PETSC_HAVE_DEVICE) && !defined(PETSC_HAVE_KOKKOS_WITHOUT_GPU)
2397   {
2398     PetscDeviceContext dctx;
2399 
2400     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2401     PetscCall(PetscDeviceContextBeginTimer_Internal(dctx));
2402   }
2403     #else
2404   PetscCall(PetscTimeSubtract(&petsc_gtime));
2405     #endif
2406   PetscFunctionReturn(PETSC_SUCCESS);
2407 }
2408 
2409 /*@
2410   PetscLogGpuTimeEnd - Stop timer for device
2411 
2412   Level: intermediate
2413 
2414 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeBegin()`
2415 @*/
2416 PetscErrorCode PetscLogGpuTimeEnd(void)
2417 {
2418   PetscBool isActive;
2419 
2420   PetscFunctionBegin;
2421   PetscCall(PetscLogEventEndIsActive(&isActive));
2422   if (!isActive || !PetscLogGpuTimeFlag) PetscFunctionReturn(PETSC_SUCCESS);
2423     #if defined(PETSC_HAVE_DEVICE) && !defined(PETSC_HAVE_KOKKOS_WITHOUT_GPU)
2424   {
2425     PetscDeviceContext dctx;
2426     PetscLogDouble     elapsed;
2427 
2428     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2429     PetscCall(PetscDeviceContextEndTimer_Internal(dctx, &elapsed));
2430     petsc_gtime += (elapsed / 1000.0);
2431   }
2432     #else
2433   PetscCall(PetscTimeAdd(&petsc_gtime));
2434     #endif
2435   PetscFunctionReturn(PETSC_SUCCESS);
2436 }
2437 
2438   #endif /* end of PETSC_HAVE_DEVICE */
2439 
2440 #endif /* PETSC_USE_LOG*/
2441 
2442 /* -- Utility functions for logging from Fortran -- */
2443 
2444 PETSC_EXTERN PetscErrorCode PetscASend(int count, int datatype)
2445 {
2446   PetscFunctionBegin;
2447 #if PetscDefined(USE_LOG)
2448   PetscCall(PetscAddLogDouble(&petsc_send_ct, &petsc_send_ct_th, 1));
2449   #if !defined(MPIUNI_H) && !defined(PETSC_HAVE_BROKEN_RECURSIVE_MACRO)
2450   PetscCall(PetscMPITypeSize(count, MPI_Type_f2c((MPI_Fint)datatype), &petsc_send_len, &petsc_send_len_th));
2451   #endif
2452 #endif
2453   PetscFunctionReturn(PETSC_SUCCESS);
2454 }
2455 
2456 PETSC_EXTERN PetscErrorCode PetscARecv(int count, int datatype)
2457 {
2458   PetscFunctionBegin;
2459 #if PetscDefined(USE_LOG)
2460   PetscCall(PetscAddLogDouble(&petsc_recv_ct, &petsc_recv_ct_th, 1));
2461   #if !defined(MPIUNI_H) && !defined(PETSC_HAVE_BROKEN_RECURSIVE_MACRO)
2462   PetscCall(PetscMPITypeSize(count, MPI_Type_f2c((MPI_Fint)datatype), &petsc_recv_len, &petsc_recv_len_th));
2463   #endif
2464 #endif
2465   PetscFunctionReturn(PETSC_SUCCESS);
2466 }
2467 
2468 PETSC_EXTERN PetscErrorCode PetscAReduce(void)
2469 {
2470   PetscFunctionBegin;
2471   if (PetscDefined(USE_LOG)) PetscCall(PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, 1));
2472   PetscFunctionReturn(PETSC_SUCCESS);
2473 }
2474 
2475 PetscClassId PETSC_LARGEST_CLASSID = PETSC_SMALLEST_CLASSID;
2476 PetscClassId PETSC_OBJECT_CLASSID  = 0;
2477 
2478 static PetscBool PetscLogInitializeCalled = PETSC_FALSE;
2479 
2480 PETSC_INTERN PetscErrorCode PetscLogInitialize(void)
2481 {
2482   int stage;
2483 
2484   PetscFunctionBegin;
2485   if (PetscLogInitializeCalled) PetscFunctionReturn(PETSC_SUCCESS);
2486   PetscLogInitializeCalled = PETSC_TRUE;
2487   if (PetscDefined(USE_LOG)) {
2488     /* Setup default logging structures */
2489     PetscCall(PetscLogStateCreate(&petsc_log_state));
2490     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
2491       if (PetscLogHandlers[i].handler) PetscCall(PetscLogHandlerSetState(PetscLogHandlers[i].handler, petsc_log_state));
2492     }
2493     PetscCall(PetscLogStateStageRegister(petsc_log_state, "Main Stage", &stage));
2494     PetscCall(PetscSpinlockCreate(&PetscLogSpinLock));
2495 #if defined(PETSC_HAVE_THREADSAFETY)
2496     petsc_log_tid = 0;
2497     petsc_log_gid = 0;
2498 #endif
2499 
2500     /* All processors sync here for more consistent logging */
2501     PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
2502     PetscCall(PetscTime(&petsc_BaseTime));
2503     PetscCall(PetscLogStagePush(stage));
2504   }
2505   PetscFunctionReturn(PETSC_SUCCESS);
2506 }
2507 
2508 PETSC_INTERN PetscErrorCode PetscLogFinalize(void)
2509 {
2510   PetscFunctionBegin;
2511   if (PetscDefined(USE_LOG)) {
2512     /* Resetting phase */
2513     // pop remaining stages
2514     if (petsc_log_state) {
2515       while (petsc_log_state->current_stage >= 0) PetscCall(PetscLogStagePop());
2516     }
2517     for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) PetscCall(PetscLogHandlerDestroy(&PetscLogHandlers[i].handler));
2518     PetscCall(PetscArrayzero(PetscLogHandlers, PETSC_LOG_HANDLER_MAX));
2519     PetscCall(PetscLogStateDestroy(&petsc_log_state));
2520 
2521     petsc_TotalFlops         = 0.0;
2522     petsc_BaseTime           = 0.0;
2523     petsc_TotalFlops         = 0.0;
2524     petsc_send_ct            = 0.0;
2525     petsc_recv_ct            = 0.0;
2526     petsc_send_len           = 0.0;
2527     petsc_recv_len           = 0.0;
2528     petsc_isend_ct           = 0.0;
2529     petsc_irecv_ct           = 0.0;
2530     petsc_isend_len          = 0.0;
2531     petsc_irecv_len          = 0.0;
2532     petsc_wait_ct            = 0.0;
2533     petsc_wait_any_ct        = 0.0;
2534     petsc_wait_all_ct        = 0.0;
2535     petsc_sum_of_waits_ct    = 0.0;
2536     petsc_allreduce_ct       = 0.0;
2537     petsc_gather_ct          = 0.0;
2538     petsc_scatter_ct         = 0.0;
2539     petsc_TotalFlops_th      = 0.0;
2540     petsc_send_ct_th         = 0.0;
2541     petsc_recv_ct_th         = 0.0;
2542     petsc_send_len_th        = 0.0;
2543     petsc_recv_len_th        = 0.0;
2544     petsc_isend_ct_th        = 0.0;
2545     petsc_irecv_ct_th        = 0.0;
2546     petsc_isend_len_th       = 0.0;
2547     petsc_irecv_len_th       = 0.0;
2548     petsc_wait_ct_th         = 0.0;
2549     petsc_wait_any_ct_th     = 0.0;
2550     petsc_wait_all_ct_th     = 0.0;
2551     petsc_sum_of_waits_ct_th = 0.0;
2552     petsc_allreduce_ct_th    = 0.0;
2553     petsc_gather_ct_th       = 0.0;
2554     petsc_scatter_ct_th      = 0.0;
2555 
2556     petsc_ctog_ct    = 0.0;
2557     petsc_gtoc_ct    = 0.0;
2558     petsc_ctog_sz    = 0.0;
2559     petsc_gtoc_sz    = 0.0;
2560     petsc_gflops     = 0.0;
2561     petsc_gtime      = 0.0;
2562     petsc_ctog_ct_th = 0.0;
2563     petsc_gtoc_ct_th = 0.0;
2564     petsc_ctog_sz_th = 0.0;
2565     petsc_gtoc_sz_th = 0.0;
2566     petsc_gflops_th  = 0.0;
2567     petsc_gtime_th   = 0.0;
2568   }
2569   PETSC_LARGEST_CLASSID    = PETSC_SMALLEST_CLASSID;
2570   PETSC_OBJECT_CLASSID     = 0;
2571   PetscLogInitializeCalled = PETSC_FALSE;
2572   PetscFunctionReturn(PETSC_SUCCESS);
2573 }
2574 
2575 /*@
2576   PetscClassIdRegister - Registers a new class name for objects and logging operations in an application code.
2577 
2578   Not Collective
2579 
2580   Input Parameter:
2581 . name - The class name
2582 
2583   Output Parameter:
2584 . oclass - The class id or classid
2585 
2586   Level: developer
2587 
2588 .seealso: [](ch_profiling), `PetscLogEventRegister()`
2589 @*/
2590 PetscErrorCode PetscClassIdRegister(const char name[], PetscClassId *oclass)
2591 {
2592   PetscFunctionBegin;
2593   *oclass = ++PETSC_LARGEST_CLASSID;
2594 #if defined(PETSC_USE_LOG)
2595   {
2596     PetscLogState state;
2597     PetscLogClass logclass;
2598 
2599     PetscCall(PetscLogGetState(&state));
2600     if (state) PetscCall(PetscLogStateClassRegister(state, name, *oclass, &logclass));
2601   }
2602 #endif
2603   PetscFunctionReturn(PETSC_SUCCESS);
2604 }
2605