xref: /petsc/src/sys/logging/plog.c (revision 174dc0c8cee294b82b85e4dd3b331b29396264fc)
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) {
346             PetscCall(PetscIntStackTop(temp_stack, &petsc_log_state->current_stage));
347           } else petsc_log_state->current_stage = -1;
348           PetscCall(PetscLogHandlerStagePop(h, stage));
349         }
350         PetscCall(PetscIntStackDestroy(temp_stack));
351         petsc_log_state->stage_stack = orig_stack;
352         PetscCall(PetscIntStackTop(petsc_log_state->stage_stack, &petsc_log_state->current_stage));
353       }
354       PetscCall(PetscArrayzero(&PetscLogHandlers[i], 1));
355       PetscCall(PetscObjectDereference((PetscObject)h));
356     }
357   }
358   PetscFunctionReturn(PETSC_SUCCESS);
359 }
360 
361 /*@
362   PetscLogIsActive - Check if logging (profiling) is currently in progress.
363 
364   Not Collective
365 
366   Output Parameter:
367 . isActive - `PETSC_TRUE` if logging is in progress, `PETSC_FALSE` otherwise
368 
369   Level: beginner
370 
371 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`
372 @*/
373 PetscErrorCode PetscLogIsActive(PetscBool *isActive)
374 {
375   PetscFunctionBegin;
376   *isActive = PETSC_FALSE;
377   if (petsc_log_state) {
378     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
379       if (PetscLogHandlers[i].handler) {
380         *isActive = PETSC_TRUE;
381         PetscFunctionReturn(PETSC_SUCCESS);
382       }
383     }
384   }
385   PetscFunctionReturn(PETSC_SUCCESS);
386 }
387 
388 PETSC_UNUSED static PetscErrorCode PetscLogEventBeginIsActive(PetscBool *isActive)
389 {
390   PetscFunctionBegin;
391   *isActive = PETSC_FALSE;
392   if (petsc_log_state) {
393     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
394       if (PetscLogHandlers[i].eventBegin) {
395         *isActive = PETSC_TRUE;
396         PetscFunctionReturn(PETSC_SUCCESS);
397       }
398     }
399   }
400   PetscFunctionReturn(PETSC_SUCCESS);
401 }
402 
403 PETSC_UNUSED static PetscErrorCode PetscLogEventEndIsActive(PetscBool *isActive)
404 {
405   PetscFunctionBegin;
406   *isActive = PETSC_FALSE;
407   if (petsc_log_state) {
408     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
409       if (PetscLogHandlers[i].eventEnd) {
410         *isActive = PETSC_TRUE;
411         PetscFunctionReturn(PETSC_SUCCESS);
412       }
413     }
414   }
415   PetscFunctionReturn(PETSC_SUCCESS);
416 }
417 
418 PETSC_INTERN PetscErrorCode PetscLogTypeBegin(PetscLogHandlerType type)
419 {
420   PetscLogHandler handler;
421 
422   PetscFunctionBegin;
423   PetscCall(PetscLogTryGetHandler(type, &handler));
424   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
425   PetscCall(PetscLogHandlerCreate(PETSC_COMM_WORLD, &handler));
426   PetscCall(PetscLogHandlerSetType(handler, type));
427   PetscCall(PetscLogHandlerStart(handler));
428   PetscCall(PetscLogHandlerDestroy(&handler));
429   PetscFunctionReturn(PETSC_SUCCESS);
430 }
431 
432 /*@
433   PetscLogDefaultBegin - Turns on logging (profiling) of PETSc code using the default log handler (profiler). This logs time, flop
434   rates, and object creation and should not slow programs down too much.
435 
436   Logically Collective on `PETSC_COMM_WORLD`
437 
438   Options Database Key:
439 . -log_view [viewertype:filename:viewerformat] - Prints summary of flop and timing (profiling) information to the
440                                                  screen (for PETSc configured with `--with-log=1` (which is the default)).
441                                                  This option must be provided before `PetscInitialize()`.
442 
443   Example Usage:
444 .vb
445       PetscInitialize(...);
446       PetscLogDefaultBegin();
447        ... code ...
448       PetscLogView(viewer); or PetscLogDump();
449       PetscFinalize();
450 .ve
451 
452   Level: advanced
453 
454   Notes:
455   `PetscLogView()` or `PetscLogDump()` actually cause the printing of
456   the logging information.
457 
458   This routine may be called more than once.
459 
460   To provide the `-log_view` option in your source code you must call  PetscCall(PetscOptionsSetValue(NULL, "-log_view", NULL));
461   before you call `PetscInitialize()`
462 
463 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`
464 @*/
465 PetscErrorCode PetscLogDefaultBegin(void)
466 {
467   PetscFunctionBegin;
468   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERDEFAULT));
469   PetscFunctionReturn(PETSC_SUCCESS);
470 }
471 
472 /*@C
473   PetscLogTraceBegin - Begins trace logging.  Every time a PETSc event
474   begins or ends, the event name is printed.
475 
476   Logically Collective on `PETSC_COMM_WORLD`, No Fortran Support
477 
478   Input Parameter:
479 . file - The file to print trace in (e.g. stdout)
480 
481   Options Database Key:
482 . -log_trace [filename] - Begins `PetscLogTraceBegin()`
483 
484   Level: intermediate
485 
486   Notes:
487   `PetscLogTraceBegin()` prints the processor number, the execution time (sec),
488   then "Event begin:" or "Event end:" followed by the event name.
489 
490   `PetscLogTraceBegin()` allows tracing of all PETSc calls, which is useful
491   to determine where a program is hanging without running in the
492   debugger.  Can be used in conjunction with the -info option.
493 
494 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogView()`, `PetscLogDefaultBegin()`
495 @*/
496 PetscErrorCode PetscLogTraceBegin(FILE *file)
497 {
498   PetscLogHandler handler;
499 
500   PetscFunctionBegin;
501   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERTRACE, &handler));
502   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
503   PetscCall(PetscLogHandlerCreateTrace(PETSC_COMM_WORLD, file, &handler));
504   PetscCall(PetscLogHandlerStart(handler));
505   PetscCall(PetscLogHandlerDestroy(&handler));
506   PetscFunctionReturn(PETSC_SUCCESS);
507 }
508 
509 PETSC_INTERN PetscErrorCode PetscLogHandlerCreate_Nested(MPI_Comm, PetscLogHandler *);
510 
511 /*@
512   PetscLogNestedBegin - Turns on nested logging of objects and events. This logs flop
513   rates and object creation and should not slow programs down too much.
514 
515   Logically Collective on `PETSC_COMM_WORLD`, No Fortran Support
516 
517   Options Database Keys:
518 . -log_view :filename.xml:ascii_xml - Prints an XML summary of flop and timing information to the file
519 
520   Example Usage:
521 .vb
522       PetscInitialize(...);
523       PetscLogNestedBegin();
524        ... code ...
525       PetscLogView(viewer);
526       PetscFinalize();
527 .ve
528 
529   Level: advanced
530 
531 .seealso: `PetscLogDump()`, `PetscLogView()`, `PetscLogTraceBegin()`, `PetscLogDefaultBegin()`
532 @*/
533 PetscErrorCode PetscLogNestedBegin(void)
534 {
535   PetscFunctionBegin;
536   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERNESTED));
537   PetscFunctionReturn(PETSC_SUCCESS);
538 }
539 
540 /*@C
541   PetscLogLegacyCallbacksBegin - Create and start a log handler from callbacks
542   matching the now deprecated function pointers `PetscLogPLB`, `PetscLogPLE`,
543   `PetscLogPHC`, `PetscLogPHD`.
544 
545   Logically Collective on `PETSC_COMM_WORLD`
546 
547   Input Parameters:
548 + PetscLogPLB - A callback that will be executed by `PetscLogEventBegin()` (or `NULL`)
549 . PetscLogPLE - A callback that will be executed by `PetscLogEventEnd()` (or `NULL`)
550 . PetscLogPHC - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)
551 - PetscLogPHD - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)
552 
553   Calling sequence of `PetscLogPLB`:
554 + e  - a `PetscLogEvent` that is beginning
555 . _i - deprecated, unused
556 . o1 - a `PetscObject` associated with `e` (or `NULL`)
557 . o2 - a `PetscObject` associated with `e` (or `NULL`)
558 . o3 - a `PetscObject` associated with `e` (or `NULL`)
559 - o4 - a `PetscObject` associated with `e` (or `NULL`)
560 
561   Calling sequence of `PetscLogPLE`:
562 + e  - a `PetscLogEvent` that is beginning
563 . _i - deprecated, unused
564 . o1 - a `PetscObject` associated with `e` (or `NULL`)
565 . o2 - a `PetscObject` associated with `e` (or `NULL`)
566 . o3 - a `PetscObject` associated with `e` (or `NULL`)
567 - o4 - a `PetscObject` associated with `e` (or `NULL`)
568 
569   Calling sequence of `PetscLogPHC`:
570 . o - a `PetscObject` that has just been created
571 
572   Calling sequence of `PetscLogPHD`:
573 . o - a `PetscObject` that is about to be destroyed
574 
575   Level: advanced
576 
577   Notes:
578   This is for transitioning from the deprecated function `PetscLogSet()` and should not be used in new code.
579 
580   This should help migrate external log handlers to use `PetscLogHandler`, but
581   callbacks that depend on the deprecated `PetscLogStage` datatype will have to be
582   updated.
583 
584 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogHandlerStart()`, `PetscLogState`
585 @*/
586 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))
587 {
588   PetscLogHandler handler;
589 
590   PetscFunctionBegin;
591   PetscCall(PetscLogHandlerCreateLegacy(PETSC_COMM_WORLD, PetscLogPLB, PetscLogPLE, PetscLogPHC, PetscLogPHD, &handler));
592   PetscCall(PetscLogHandlerStart(handler));
593   PetscCall(PetscLogHandlerDestroy(&handler));
594   PetscFunctionReturn(PETSC_SUCCESS);
595 }
596 
597   #if defined(PETSC_HAVE_MPE)
598     #include <mpe.h>
599 static PetscBool PetscBeganMPE = PETSC_FALSE;
600   #endif
601 
602 /*@C
603   PetscLogMPEBegin - Turns on MPE logging of events. This creates large log files and slows the
604   program down.
605 
606   Collective on `PETSC_COMM_WORLD`, No Fortran Support
607 
608   Options Database Key:
609 . -log_mpe - Prints extensive log information
610 
611   Level: advanced
612 
613   Note:
614   A related routine is `PetscLogDefaultBegin()` (with the options key `-log_view`), which is
615   intended for production runs since it logs only flop rates and object creation (and should
616   not significantly slow the programs).
617 
618 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogDefaultBegin()`, `PetscLogEventActivate()`,
619           `PetscLogEventDeactivate()`
620 @*/
621 PetscErrorCode PetscLogMPEBegin(void)
622 {
623   PetscFunctionBegin;
624   #if defined(PETSC_HAVE_MPE)
625   /* Do MPE initialization */
626   if (!MPE_Initialized_logging()) { /* This function exists in mpich 1.1.2 and higher */
627     PetscCall(PetscInfo(0, "Initializing MPE.\n"));
628     PetscCall(MPE_Init_log());
629 
630     PetscBeganMPE = PETSC_TRUE;
631   } else {
632     PetscCall(PetscInfo(0, "MPE already initialized. Not attempting to reinitialize.\n"));
633   }
634   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERMPE));
635   #else
636   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
637   #endif
638   PetscFunctionReturn(PETSC_SUCCESS);
639 }
640 
641   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
642     #include <../src/sys/perfstubs/timer.h>
643   #endif
644 
645 /*@C
646   PetscLogPerfstubsBegin - Turns on logging of events using the perfstubs interface.
647 
648   Collective on `PETSC_COMM_WORLD`, No Fortran Support
649 
650   Options Database Key:
651 . -log_perfstubs - use an external log handler through the perfstubs interface
652 
653   Level: advanced
654 
655 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogEventActivate()`
656 @*/
657 PetscErrorCode PetscLogPerfstubsBegin(void)
658 {
659   PetscFunctionBegin;
660   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
661   PetscCall(PetscLogTypeBegin(PETSCLOGHANDLERPERFSTUBS));
662   #else
663   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without perfstubs support, reconfigure with --with-tau-perfstubs");
664   #endif
665   PetscFunctionReturn(PETSC_SUCCESS);
666 }
667 
668 /*@
669   PetscLogActions - Determines whether actions are logged for the default log handler.
670 
671   Not Collective
672 
673   Input Parameter:
674 . flag - `PETSC_TRUE` if actions are to be logged
675 
676   Options Database Key:
677 + -log_exclude_actions - (deprecated) Does nothing
678 - -log_include_actions - Turn on action logging
679 
680   Level: intermediate
681 
682   Note:
683   Logging of actions continues to consume more memory as the program
684   runs. Long running programs should consider turning this feature off.
685 
686 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogGetDefaultHandler()`
687 @*/
688 PetscErrorCode PetscLogActions(PetscBool flag)
689 {
690   PetscFunctionBegin;
691   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
692     PetscLogHandler h = PetscLogHandlers[i].handler;
693 
694     if (h) PetscCall(PetscLogHandlerSetLogActions(h, flag));
695   }
696   PetscFunctionReturn(PETSC_SUCCESS);
697 }
698 
699 /*@
700   PetscLogObjects - Determines whether objects are logged for the graphical viewer.
701 
702   Not Collective
703 
704   Input Parameter:
705 . flag - `PETSC_TRUE` if objects are to be logged
706 
707   Options Database Key:
708 + -log_exclude_objects - (deprecated) Does nothing
709 - -log_include_objects - Turns on object logging
710 
711   Level: intermediate
712 
713   Note:
714   Logging of objects continues to consume more memory as the program
715   runs. Long running programs should consider turning this feature off.
716 
717 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogGetDefaultHandler()`
718 @*/
719 PetscErrorCode PetscLogObjects(PetscBool flag)
720 {
721   PetscFunctionBegin;
722   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
723     PetscLogHandler h = PetscLogHandlers[i].handler;
724 
725     if (h) PetscCall(PetscLogHandlerSetLogObjects(h, flag));
726   }
727   PetscFunctionReturn(PETSC_SUCCESS);
728 }
729 
730 /*------------------------------------------------ Stage Functions --------------------------------------------------*/
731 /*@
732   PetscLogStageRegister - Attaches a character string name to a logging stage.
733 
734   Not Collective
735 
736   Input Parameter:
737 . sname - The name to associate with that stage
738 
739   Output Parameter:
740 . stage - The stage number or -1 if logging is not active (`PetscLogIsActive()`).
741 
742   Level: intermediate
743 
744 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`
745 @*/
746 PetscErrorCode PetscLogStageRegister(const char sname[], PetscLogStage *stage)
747 {
748   PetscLogState state;
749 
750   PetscFunctionBegin;
751   *stage = -1;
752   PetscCall(PetscLogGetState(&state));
753   if (state) PetscCall(PetscLogStateStageRegister(state, sname, stage));
754   PetscFunctionReturn(PETSC_SUCCESS);
755 }
756 
757 /*@
758   PetscLogStagePush - This function pushes a stage on the logging stack. Events started and stopped until `PetscLogStagePop()` will be associated with the stage
759 
760   Not Collective
761 
762   Input Parameter:
763 . stage - The stage on which to log
764 
765   Example Usage:
766   If the option -log_view is used to run the program containing the
767   following code, then 2 sets of summary data will be printed during
768   PetscFinalize().
769 .vb
770       PetscInitialize(int *argc,char ***args,0,0);
771       [stage 0 of code]
772       PetscLogStagePush(1);
773       [stage 1 of code]
774       PetscLogStagePop();
775       PetscBarrier(...);
776       [more stage 0 of code]
777       PetscFinalize();
778 .ve
779 
780   Level: intermediate
781 
782   Note:
783   Use `PetscLogStageRegister()` to register a stage.
784 
785 .seealso: [](ch_profiling), `PetscLogStagePop()`, `PetscLogStageRegister()`, `PetscBarrier()`
786 @*/
787 PetscErrorCode PetscLogStagePush(PetscLogStage stage)
788 {
789   PetscLogState state;
790 
791   PetscFunctionBegin;
792   PetscCall(PetscLogGetState(&state));
793   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
794   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
795     PetscLogHandler h = PetscLogHandlers[i].handler;
796     if (h) PetscCall(PetscLogHandlerStagePush(h, stage));
797   }
798   PetscCall(PetscLogStateStagePush(state, stage));
799   PetscFunctionReturn(PETSC_SUCCESS);
800 }
801 
802 /*@
803   PetscLogStagePop - This function pops a stage from the logging stack that was pushed with `PetscLogStagePush()`
804 
805   Not Collective
806 
807   Example Usage:
808   If the option -log_view is used to run the program containing the
809   following code, then 2 sets of summary data will be printed during
810   PetscFinalize().
811 .vb
812       PetscInitialize(int *argc,char ***args,0,0);
813       [stage 0 of code]
814       PetscLogStagePush(1);
815       [stage 1 of code]
816       PetscLogStagePop();
817       PetscBarrier(...);
818       [more stage 0 of code]
819       PetscFinalize();
820 .ve
821 
822   Level: intermediate
823 
824 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStageRegister()`, `PetscBarrier()`
825 @*/
826 PetscErrorCode PetscLogStagePop(void)
827 {
828   PetscLogState state;
829   PetscLogStage current_stage;
830 
831   PetscFunctionBegin;
832   PetscCall(PetscLogGetState(&state));
833   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
834   current_stage = state->current_stage;
835   PetscCall(PetscLogStateStagePop(state));
836   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
837     PetscLogHandler h = PetscLogHandlers[i].handler;
838     if (h) PetscCall(PetscLogHandlerStagePop(h, current_stage));
839   }
840   PetscFunctionReturn(PETSC_SUCCESS);
841 }
842 
843 /*@
844   PetscLogStageSetActive - Sets if a stage is used for `PetscLogEventBegin()` and `PetscLogEventEnd()`.
845 
846   Not Collective
847 
848   Input Parameters:
849 + stage    - The stage
850 - isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
851 
852   Level: intermediate
853 
854   Note:
855   If this is set to `PETSC_FALSE` the logging acts as if the stage did not exist
856 
857 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
858 @*/
859 PetscErrorCode PetscLogStageSetActive(PetscLogStage stage, PetscBool isActive)
860 {
861   PetscLogState state;
862 
863   PetscFunctionBegin;
864   PetscCall(PetscLogGetState(&state));
865   if (state) PetscCall(PetscLogStateStageSetActive(state, stage, isActive));
866   PetscFunctionReturn(PETSC_SUCCESS);
867 }
868 
869 /*@
870   PetscLogStageGetActive - Checks if a stage is used for `PetscLogEventBegin()` and `PetscLogEventEnd()`.
871 
872   Not Collective
873 
874   Input Parameter:
875 . stage - The stage
876 
877   Output Parameter:
878 . isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
879 
880   Level: intermediate
881 
882 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
883 @*/
884 PetscErrorCode PetscLogStageGetActive(PetscLogStage stage, PetscBool *isActive)
885 {
886   PetscLogState state;
887 
888   PetscFunctionBegin;
889   *isActive = PETSC_FALSE;
890   PetscCall(PetscLogGetState(&state));
891   if (state) PetscCall(PetscLogStateStageGetActive(state, stage, isActive));
892   PetscFunctionReturn(PETSC_SUCCESS);
893 }
894 
895 /*@
896   PetscLogStageSetVisible - Determines stage visibility in `PetscLogView()`
897 
898   Not Collective
899 
900   Input Parameters:
901 + stage     - The stage
902 - isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
903 
904   Level: intermediate
905 
906   Developer Notes:
907   Visibility only affects the default log handler in `PetscLogView()`: stages that are
908   set to invisible are suppressed from output.
909 
910 .seealso: [](ch_profiling), `PetscLogStageGetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
911 @*/
912 PetscErrorCode PetscLogStageSetVisible(PetscLogStage stage, PetscBool isVisible)
913 
914 {
915   PetscFunctionBegin;
916   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
917     PetscLogHandler h = PetscLogHandlers[i].handler;
918 
919     if (h) PetscCall(PetscLogHandlerStageSetVisible(h, stage, isVisible));
920   }
921   PetscFunctionReturn(PETSC_SUCCESS);
922 }
923 
924 /*@
925   PetscLogStageGetVisible - Returns stage visibility in `PetscLogView()`
926 
927   Not Collective
928 
929   Input Parameter:
930 . stage - The stage
931 
932   Output Parameter:
933 . isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
934 
935   Level: intermediate
936 
937 .seealso: [](ch_profiling), `PetscLogStageSetVisible()`, `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
938 @*/
939 PetscErrorCode PetscLogStageGetVisible(PetscLogStage stage, PetscBool *isVisible)
940 {
941   PetscLogHandler handler;
942 
943   PetscFunctionBegin;
944   *isVisible = PETSC_FALSE;
945   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
946   if (handler) { PetscCall(PetscLogHandlerStageGetVisible(handler, stage, isVisible)); }
947   PetscFunctionReturn(PETSC_SUCCESS);
948 }
949 
950 /*@
951   PetscLogStageGetId - Returns the stage id when given the stage name.
952 
953   Not Collective
954 
955   Input Parameter:
956 . name - The stage name
957 
958   Output Parameter:
959 . stage - The stage, , or -1 if no stage with that name exists
960 
961   Level: intermediate
962 
963 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
964 @*/
965 PetscErrorCode PetscLogStageGetId(const char name[], PetscLogStage *stage)
966 {
967   PetscLogState state;
968 
969   PetscFunctionBegin;
970   *stage = -1;
971   PetscCall(PetscLogGetState(&state));
972   if (state) PetscCall(PetscLogStateGetStageFromName(state, name, stage));
973   PetscFunctionReturn(PETSC_SUCCESS);
974 }
975 
976 /*@
977   PetscLogStageGetName - Returns the stage name when given the stage id.
978 
979   Not Collective
980 
981   Input Parameter:
982 . stage - The stage
983 
984   Output Parameter:
985 . name - The stage name
986 
987   Level: intermediate
988 
989 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
990 @*/
991 PetscErrorCode PetscLogStageGetName(PetscLogStage stage, const char *name[])
992 {
993   PetscLogStageInfo stage_info;
994   PetscLogState     state;
995 
996   PetscFunctionBegin;
997   *name = NULL;
998   PetscCall(PetscLogGetState(&state));
999   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
1000   PetscCall(PetscLogStateStageGetInfo(state, stage, &stage_info));
1001   *name = stage_info.name;
1002   PetscFunctionReturn(PETSC_SUCCESS);
1003 }
1004 
1005 /*------------------------------------------------ Event Functions --------------------------------------------------*/
1006 
1007 /*@
1008   PetscLogEventRegister - Registers an event name for logging operations
1009 
1010   Not Collective
1011 
1012   Input Parameters:
1013 + name    - The name associated with the event
1014 - classid - The classid associated to the class for this event, obtain either with
1015            `PetscClassIdRegister()` or use a predefined one such as `KSP_CLASSID`, `SNES_CLASSID`, the predefined ones
1016            are only available in C code
1017 
1018   Output Parameter:
1019 . event - The event id for use with `PetscLogEventBegin()` and `PetscLogEventEnd()`.
1020 
1021   Example Usage:
1022 .vb
1023       PetscLogEvent USER_EVENT;
1024       PetscClassId classid;
1025       PetscLogDouble user_event_flops;
1026       PetscClassIdRegister("class name",&classid);
1027       PetscLogEventRegister("User event name",classid,&USER_EVENT);
1028       PetscLogEventBegin(USER_EVENT,0,0,0,0);
1029          [code segment to monitor]
1030          PetscLogFlops(user_event_flops);
1031       PetscLogEventEnd(USER_EVENT,0,0,0,0);
1032 .ve
1033 
1034   Level: intermediate
1035 
1036   Notes:
1037   PETSc automatically logs library events if the code has been
1038   configured with --with-log (which is the default) and
1039   -log_view or -log_all is specified.  `PetscLogEventRegister()` is
1040   intended for logging user events to supplement this PETSc
1041   information.
1042 
1043   PETSc can gather data for use with the utilities Jumpshot
1044   (part of the MPICH distribution).  If PETSc has been compiled
1045   with flag -DPETSC_HAVE_MPE (MPE is an additional utility within
1046   MPICH), the user can employ another command line option, -log_mpe,
1047   to create a logfile, "mpe.log", which can be visualized
1048   Jumpshot.
1049 
1050   The classid is associated with each event so that classes of events
1051   can be disabled simultaneously, such as all matrix events. The user
1052   can either use an existing classid, such as `MAT_CLASSID`, or create
1053   their own as shown in the example.
1054 
1055   If an existing event with the same name exists, its event handle is
1056   returned instead of creating a new event.
1057 
1058 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogFlops()`,
1059           `PetscLogEventActivate()`, `PetscLogEventDeactivate()`, `PetscClassIdRegister()`
1060 @*/
1061 PetscErrorCode PetscLogEventRegister(const char name[], PetscClassId classid, PetscLogEvent *event)
1062 {
1063   PetscLogState state;
1064 
1065   PetscFunctionBegin;
1066   *event = -1;
1067   PetscCall(PetscLogGetState(&state));
1068   if (state) PetscCall(PetscLogStateEventRegister(state, name, classid, event));
1069   PetscFunctionReturn(PETSC_SUCCESS);
1070 }
1071 
1072 /*@
1073   PetscLogEventSetCollective - Indicates that a particular event is collective.
1074 
1075   Logically Collective
1076 
1077   Input Parameters:
1078 + event      - The event id
1079 - collective - `PetscBool` indicating whether a particular event is collective
1080 
1081   Level: developer
1082 
1083   Notes:
1084   New events returned from `PetscLogEventRegister()` are collective by default.
1085 
1086   Collective events are handled specially if the command line option `-log_sync` is used. In that case the logging saves information about
1087   two parts of the event; the time for all the MPI ranks to synchronize and then the time for the actual computation/communication
1088   to be performed. This option is useful to debug imbalance within the computations or communications.
1089 
1090 .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogEventRegister()`
1091 @*/
1092 PetscErrorCode PetscLogEventSetCollective(PetscLogEvent event, PetscBool collective)
1093 {
1094   PetscLogState state;
1095 
1096   PetscFunctionBegin;
1097   PetscCall(PetscLogGetState(&state));
1098   if (state) PetscCall(PetscLogStateEventSetCollective(state, event, collective));
1099   PetscFunctionReturn(PETSC_SUCCESS);
1100 }
1101 
1102 /*
1103   PetscLogClassSetActiveAll - Activate or inactivate logging for all events associated with a PETSc object class in every stage.
1104 
1105   Not Collective
1106 
1107   Input Parameters:
1108 + classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1109 - isActive - if `PETSC_FALSE`, events associated with this class will not be send to log handlers.
1110 
1111   Level: developer
1112 
1113 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`, `PetscLogEventActivateClass()`
1114 */
1115 static PetscErrorCode PetscLogClassSetActiveAll(PetscClassId classid, PetscBool isActive)
1116 {
1117   PetscLogState state;
1118 
1119   PetscFunctionBegin;
1120   PetscCall(PetscLogGetState(&state));
1121   if (state) PetscCall(PetscLogStateClassSetActiveAll(state, classid, isActive));
1122   PetscFunctionReturn(PETSC_SUCCESS);
1123 }
1124 
1125 /*@
1126   PetscLogEventIncludeClass - Activates event logging for a PETSc object class in every stage.
1127 
1128   Not Collective
1129 
1130   Input Parameter:
1131 . classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1132 
1133   Level: developer
1134 
1135 .seealso: [](ch_profiling), `PetscLogEventActivateClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1136 @*/
1137 PetscErrorCode PetscLogEventIncludeClass(PetscClassId classid)
1138 {
1139   PetscFunctionBegin;
1140   PetscCall(PetscLogClassSetActiveAll(classid, PETSC_TRUE));
1141   PetscFunctionReturn(PETSC_SUCCESS);
1142 }
1143 
1144 /*@
1145   PetscLogEventExcludeClass - Deactivates event logging for a PETSc object class in every stage.
1146 
1147   Not Collective
1148 
1149   Input Parameter:
1150 . classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1151 
1152   Level: developer
1153 
1154   Note:
1155   If a class is excluded then events associated with that class are not logged.
1156 
1157 .seealso: [](ch_profiling), `PetscLogEventDeactivateClass()`, `PetscLogEventActivateClass()`, `PetscLogEventDeactivate()`, `PetscLogEventActivate()`
1158 @*/
1159 PetscErrorCode PetscLogEventExcludeClass(PetscClassId classid)
1160 {
1161   PetscFunctionBegin;
1162   PetscCall(PetscLogClassSetActiveAll(classid, PETSC_FALSE));
1163   PetscFunctionReturn(PETSC_SUCCESS);
1164 }
1165 
1166 /*
1167   PetscLogEventSetActive - Activate or inactivate logging for an event in a given stage
1168 
1169   Not Collective
1170 
1171   Input Parameters:
1172 + stage - A registered `PetscLogStage` (or `PETSC_DEFAULT` for the current stage)
1173 . event - A `PetscLogEvent`
1174 - isActive - If `PETSC_FALSE`, activity from this event (`PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogEventSync()`) will not be sent to log handlers during this stage
1175 
1176   Usage:
1177 .vb
1178       PetscLogEventSetActive(VEC_SetValues, PETSC_FALSE);
1179         [code where you do not want to log VecSetValues()]
1180       PetscLogEventSetActive(VEC_SetValues, PETSC_TRUE);
1181         [code where you do want to log VecSetValues()]
1182 .ve
1183 
1184   Level: advanced
1185 
1186   Note:
1187   The event may be either a pre-defined PETSc event (found in include/petsclog.h)
1188   or an event number obtained with `PetscLogEventRegister()`.
1189 
1190 .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1191 */
1192 static PetscErrorCode PetscLogEventSetActive(PetscLogStage stage, PetscLogEvent event, PetscBool isActive)
1193 {
1194   PetscLogState state;
1195 
1196   PetscFunctionBegin;
1197   PetscCall(PetscLogGetState(&state));
1198   if (state) PetscCall(PetscLogStateEventSetActive(state, stage, event, isActive));
1199   PetscFunctionReturn(PETSC_SUCCESS);
1200 }
1201 
1202 /*@
1203   PetscLogEventActivate - Indicates that a particular event should be logged.
1204 
1205   Not Collective
1206 
1207   Input Parameter:
1208 . event - The event id
1209 
1210   Example Usage:
1211 .vb
1212       PetscLogEventDeactivate(VEC_SetValues);
1213         [code where you do not want to log VecSetValues()]
1214       PetscLogEventActivate(VEC_SetValues);
1215         [code where you do want to log VecSetValues()]
1216 .ve
1217 
1218   Level: advanced
1219 
1220   Note:
1221   The event may be either a pre-defined PETSc event (found in include/petsclog.h)
1222   or an event number obtained with `PetscLogEventRegister()`.
1223 
1224 .seealso: [](ch_profiling), `PetscLogEventDeactivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1225 @*/
1226 PetscErrorCode PetscLogEventActivate(PetscLogEvent event)
1227 {
1228   PetscFunctionBegin;
1229   PetscCall(PetscLogEventSetActive(PETSC_DEFAULT, event, PETSC_TRUE));
1230   PetscFunctionReturn(PETSC_SUCCESS);
1231 }
1232 
1233 /*@
1234   PetscLogEventDeactivate - Indicates that a particular event should not be logged.
1235 
1236   Not Collective
1237 
1238   Input Parameter:
1239 . event - The event id
1240 
1241   Example Usage:
1242 .vb
1243       PetscLogEventDeactivate(VEC_SetValues);
1244         [code where you do not want to log VecSetValues()]
1245       PetscLogEventActivate(VEC_SetValues);
1246         [code where you do want to log VecSetValues()]
1247 .ve
1248 
1249   Level: advanced
1250 
1251   Note:
1252   The event may be either a pre-defined PETSc event (found in
1253   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).
1254 
1255 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1256 @*/
1257 PetscErrorCode PetscLogEventDeactivate(PetscLogEvent event)
1258 {
1259   PetscFunctionBegin;
1260   PetscCall(PetscLogEventSetActive(PETSC_DEFAULT, event, PETSC_FALSE));
1261   PetscFunctionReturn(PETSC_SUCCESS);
1262 }
1263 
1264 /*@
1265   PetscLogEventDeactivatePush - Indicates that a particular event should not be logged until `PetscLogEventDeactivatePop()` is called
1266 
1267   Not Collective
1268 
1269   Input Parameter:
1270 . event - The event id
1271 
1272   Example Usage:
1273 .vb
1274       PetscLogEventDeactivatePush(VEC_SetValues);
1275         [code where you do not want to log VecSetValues()]
1276       PetscLogEventDeactivatePop(VEC_SetValues);
1277         [code where you do want to log VecSetValues()]
1278 .ve
1279 
1280   Level: advanced
1281 
1282   Note:
1283   The event may be either a pre-defined PETSc event (found in
1284   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).
1285 
1286   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.
1287 
1288 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivate()`, `PetscLogEventDeactivatePop()`
1289 @*/
1290 PetscErrorCode PetscLogEventDeactivatePush(PetscLogEvent event)
1291 {
1292   PetscFunctionBegin;
1293   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1294     PetscLogHandler h = PetscLogHandlers[i].handler;
1295 
1296     if (h) PetscCall(PetscLogHandlerEventDeactivatePush(h, PETSC_DEFAULT, event));
1297   }
1298   PetscFunctionReturn(PETSC_SUCCESS);
1299 }
1300 
1301 /*@
1302   PetscLogEventDeactivatePop - Indicates that a particular event should again be logged after the logging was turned off with `PetscLogEventDeactivatePush()`
1303 
1304   Not Collective
1305 
1306   Input Parameter:
1307 . event - The event id
1308 
1309   Example Usage:
1310 .vb
1311       PetscLogEventDeactivatePush(VEC_SetValues);
1312         [code where you do not want to log VecSetValues()]
1313       PetscLogEventDeactivatePop(VEC_SetValues);
1314         [code where you do want to log VecSetValues()]
1315 .ve
1316 
1317   Level: advanced
1318 
1319   Note:
1320   The event may be either a pre-defined PETSc event (found in
1321   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).
1322 
1323 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`
1324 @*/
1325 PetscErrorCode PetscLogEventDeactivatePop(PetscLogEvent event)
1326 {
1327   PetscFunctionBegin;
1328   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1329     PetscLogHandler h = PetscLogHandlers[i].handler;
1330 
1331     if (h) PetscCall(PetscLogHandlerEventDeactivatePop(h, PETSC_DEFAULT, event));
1332   }
1333   PetscFunctionReturn(PETSC_SUCCESS);
1334 }
1335 
1336 /*@
1337   PetscLogEventSetActiveAll - Turns on logging of all events
1338 
1339   Not Collective
1340 
1341   Input Parameters:
1342 + event    - The event id
1343 - isActive - The activity flag determining whether the event is logged
1344 
1345   Level: advanced
1346 
1347 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1348 @*/
1349 PetscErrorCode PetscLogEventSetActiveAll(PetscLogEvent event, PetscBool isActive)
1350 {
1351   PetscLogState state;
1352 
1353   PetscFunctionBegin;
1354   PetscCall(PetscLogGetState(&state));
1355   if (state) PetscCall(PetscLogStateEventSetActiveAll(state, event, isActive));
1356   PetscFunctionReturn(PETSC_SUCCESS);
1357 }
1358 
1359 /*
1360   PetscLogClassSetActive - Activates event logging for a PETSc object class for the current stage
1361 
1362   Not Collective
1363 
1364   Input Parameters:
1365 + stage - A registered `PetscLogStage` (or `PETSC_DEFAULT` for the current stage)
1366 . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1367 - isActive - If `PETSC_FALSE`, events associated with this class are not sent to log handlers.
1368 
1369   Level: developer
1370 
1371 .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventActivate()`, `PetscLogEventActivateAll()`, `PetscLogStageSetActive()`
1372 */
1373 static PetscErrorCode PetscLogClassSetActive(PetscLogStage stage, PetscClassId classid, PetscBool isActive)
1374 {
1375   PetscLogState state;
1376 
1377   PetscFunctionBegin;
1378   PetscCall(PetscLogGetState(&state));
1379   if (state) PetscCall(PetscLogStateClassSetActive(state, stage, classid, isActive));
1380   PetscFunctionReturn(PETSC_SUCCESS);
1381 }
1382 
1383 /*@
1384   PetscLogEventActivateClass - Activates event logging for a PETSc object class for the current stage
1385 
1386   Not Collective
1387 
1388   Input Parameter:
1389 . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1390 
1391   Level: developer
1392 
1393 .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1394 @*/
1395 PetscErrorCode PetscLogEventActivateClass(PetscClassId classid)
1396 {
1397   PetscFunctionBegin;
1398   PetscCall(PetscLogClassSetActive(PETSC_DEFAULT, classid, PETSC_TRUE));
1399   PetscFunctionReturn(PETSC_SUCCESS);
1400 }
1401 
1402 /*@
1403   PetscLogEventDeactivateClass - Deactivates event logging for a PETSc object class for the current stage
1404 
1405   Not Collective
1406 
1407   Input Parameter:
1408 . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1409 
1410   Level: developer
1411 
1412 .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventActivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1413 @*/
1414 PetscErrorCode PetscLogEventDeactivateClass(PetscClassId classid)
1415 {
1416   PetscFunctionBegin;
1417   PetscCall(PetscLogClassSetActive(PETSC_DEFAULT, classid, PETSC_FALSE));
1418   PetscFunctionReturn(PETSC_SUCCESS);
1419 }
1420 
1421 /*MC
1422   PetscLogEventSync - Synchronizes the beginning of a user event.
1423 
1424   Synopsis:
1425   #include <petsclog.h>
1426   PetscErrorCode PetscLogEventSync(PetscLogEvent e, MPI_Comm comm)
1427 
1428   Collective
1429 
1430   Input Parameters:
1431 + e    - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1432 - comm - an MPI communicator
1433 
1434   Example Usage:
1435 .vb
1436   PetscLogEvent USER_EVENT;
1437 
1438   PetscLogEventRegister("User event", 0, &USER_EVENT);
1439   PetscLogEventSync(USER_EVENT, PETSC_COMM_WORLD);
1440   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1441   [code segment to monitor]
1442   PetscLogEventEnd(USER_EVENT, 0, 0, 0 , 0);
1443 .ve
1444 
1445   Level: developer
1446 
1447   Note:
1448   This routine should be called only if there is not a `PetscObject` available to pass to
1449   `PetscLogEventBegin()`.
1450 
1451 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`
1452 M*/
1453 
1454 /*MC
1455   PetscLogEventBegin - Logs the beginning of a user event.
1456 
1457   Synopsis:
1458   #include <petsclog.h>
1459   PetscErrorCode PetscLogEventBegin(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
1460 
1461   Not Collective
1462 
1463   Input Parameters:
1464 + e  - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1465 . o1 - object associated with the event, or `NULL`
1466 . o2 - object associated with the event, or `NULL`
1467 . o3 - object associated with the event, or `NULL`
1468 - o4 - object associated with the event, or `NULL`
1469 
1470   Fortran Synopsis:
1471   void PetscLogEventBegin(int e, PetscErrorCode ierr)
1472 
1473   Example Usage:
1474 .vb
1475   PetscLogEvent USER_EVENT;
1476 
1477   PetscLogDouble user_event_flops;
1478   PetscLogEventRegister("User event",0, &USER_EVENT);
1479   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1480   [code segment to monitor]
1481   PetscLogFlops(user_event_flops);
1482   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
1483 .ve
1484 
1485   Level: intermediate
1486 
1487   Developer Note:
1488   `PetscLogEventBegin()` and `PetscLogEventBegin()` return error codes instead of explicitly
1489   handling the errors that occur in the macro directly because other packages that use this
1490   macros have used them in their own functions or methods that do not return error codes and it
1491   would be disruptive to change the current behavior.
1492 
1493 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventEnd()`, `PetscLogFlops()`
1494 M*/
1495 
1496 /*MC
1497   PetscLogEventEnd - Log the end of a user event.
1498 
1499   Synopsis:
1500   #include <petsclog.h>
1501   PetscErrorCode PetscLogEventEnd(PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
1502 
1503   Not Collective
1504 
1505   Input Parameters:
1506 + e  - `PetscLogEvent` obtained from `PetscLogEventRegister()`
1507 . o1 - object associated with the event, or `NULL`
1508 . o2 - object associated with the event, or `NULL`
1509 . o3 - object associated with the event, or `NULL`
1510 - o4 - object associated with the event, or `NULL`
1511 
1512   Fortran Synopsis:
1513   void PetscLogEventEnd(int e, PetscErrorCode ierr)
1514 
1515   Example Usage:
1516 .vb
1517   PetscLogEvent USER_EVENT;
1518 
1519   PetscLogDouble user_event_flops;
1520   PetscLogEventRegister("User event", 0, &USER_EVENT);
1521   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1522   [code segment to monitor]
1523   PetscLogFlops(user_event_flops);
1524   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
1525 .ve
1526 
1527   Level: intermediate
1528 
1529 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogFlops()`
1530 M*/
1531 
1532 /*@C
1533   PetscLogStageGetPerfInfo - Return the performance information about the given stage
1534 
1535   No Fortran Support
1536 
1537   Input Parameters:
1538 . stage - The stage number or `PETSC_DETERMINE` for the current stage
1539 
1540   Output Parameter:
1541 . info - This structure is filled with the performance information
1542 
1543   Level: intermediate
1544 
1545   Notes:
1546   This is a low level routine used by the logging functions in PETSc.
1547 
1548   A `PETSCLOGHANDLERDEFAULT` must be running for this to work, having been started either with
1549   `PetscLogDefaultBegin()` or from the command line with `-log_view`.  If it was not started,
1550   all performance statistics in `info` will be zeroed.
1551 
1552 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogGetDefaultHandler()`
1553 @*/
1554 PetscErrorCode PetscLogStageGetPerfInfo(PetscLogStage stage, PetscEventPerfInfo *info)
1555 {
1556   PetscLogHandler     handler;
1557   PetscEventPerfInfo *event_info;
1558 
1559   PetscFunctionBegin;
1560   PetscAssertPointer(info, 2);
1561   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1562   if (handler) {
1563     PetscCall(PetscLogHandlerGetStagePerfInfo(handler, stage, &event_info));
1564     *info = *event_info;
1565   } else {
1566     PetscCall(PetscInfo(NULL, "Default log handler is not running, PetscLogStageGetPerfInfo() returning zeros\n"));
1567     PetscCall(PetscMemzero(info, sizeof(*info)));
1568   }
1569   PetscFunctionReturn(PETSC_SUCCESS);
1570 }
1571 
1572 /*@C
1573   PetscLogEventGetPerfInfo - Return the performance information about the given event in the given stage
1574 
1575   No Fortran Support
1576 
1577   Input Parameters:
1578 + stage - The stage number or `PETSC_DETERMINE` for the current stage
1579 - event - The event number
1580 
1581   Output Parameter:
1582 . info - This structure is filled with the performance information
1583 
1584   Level: intermediate
1585 
1586   Note:
1587   This is a low level routine used by the logging functions in PETSc
1588 
1589   A `PETSCLOGHANDLERDEFAULT` must be running for this to work, having been started either with
1590   `PetscLogDefaultBegin()` or from the command line with `-log_view`.  If it was not started,
1591   all performance statistics in `info` will be zeroed.
1592 
1593 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogGetDefaultHandler()`
1594 @*/
1595 PetscErrorCode PetscLogEventGetPerfInfo(PetscLogStage stage, PetscLogEvent event, PetscEventPerfInfo *info)
1596 {
1597   PetscLogHandler     handler;
1598   PetscEventPerfInfo *event_info;
1599 
1600   PetscFunctionBegin;
1601   PetscAssertPointer(info, 3);
1602   PetscCall(PetscLogTryGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1603   if (handler) {
1604     PetscCall(PetscLogHandlerGetEventPerfInfo(handler, stage, event, &event_info));
1605     *info = *event_info;
1606   } else {
1607     PetscCall(PetscInfo(NULL, "Default log handler is not running, PetscLogEventGetPerfInfo() returning zeros\n"));
1608     PetscCall(PetscMemzero(info, sizeof(*info)));
1609   }
1610   PetscFunctionReturn(PETSC_SUCCESS);
1611 }
1612 
1613 /*@
1614   PetscLogEventSetDof - Set the nth number of degrees of freedom of a numerical problem associated with this event
1615 
1616   Not Collective
1617 
1618   Input Parameters:
1619 + event - The event id to log
1620 . n     - The dof index, in [0, 8)
1621 - dof   - The number of dofs
1622 
1623   Options Database Key:
1624 . -log_view - Activates log summary
1625 
1626   Level: developer
1627 
1628   Note:
1629   This is to enable logging of convergence
1630 
1631 .seealso: `PetscLogEventSetError()`, `PetscLogEventRegister()`, `PetscLogGetDefaultHandler()`
1632 @*/
1633 PetscErrorCode PetscLogEventSetDof(PetscLogEvent event, PetscInt n, PetscLogDouble dof)
1634 {
1635   PetscFunctionBegin;
1636   PetscCheck(!(n < 0) && !(n > 7), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Error index %" PetscInt_FMT " is not in [0, 8)", n);
1637   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1638     PetscLogHandler h = PetscLogHandlers[i].handler;
1639 
1640     if (h) {
1641       PetscEventPerfInfo *event_info;
1642 
1643       PetscCall(PetscLogHandlerGetEventPerfInfo(h, PETSC_DEFAULT, event, &event_info));
1644       if (event_info) event_info->dof[n] = dof;
1645     }
1646   }
1647   PetscFunctionReturn(PETSC_SUCCESS);
1648 }
1649 
1650 /*@
1651   PetscLogEventSetError - Set the nth error associated with a numerical problem associated with this event
1652 
1653   Not Collective
1654 
1655   Input Parameters:
1656 + event - The event id to log
1657 . n     - The error index, in [0, 8)
1658 - error - The error
1659 
1660   Options Database Key:
1661 . -log_view - Activates log summary
1662 
1663   Level: developer
1664 
1665   Notes:
1666   This is to enable logging of convergence, and enable users to interpret the errors as they wish. For example,
1667   as different norms, or as errors for different fields
1668 
1669   This is a low level routine used by the logging functions in PETSc
1670 
1671 .seealso: `PetscLogEventSetDof()`, `PetscLogEventRegister()`, `PetscLogGetDefaultHandler()`
1672 @*/
1673 PetscErrorCode PetscLogEventSetError(PetscLogEvent event, PetscInt n, PetscLogDouble error)
1674 {
1675   PetscFunctionBegin;
1676   PetscCheck(!(n < 0) && !(n > 7), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Error index %" PetscInt_FMT " is not in [0, 8)", n);
1677   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1678     PetscLogHandler h = PetscLogHandlers[i].handler;
1679 
1680     if (h) {
1681       PetscEventPerfInfo *event_info;
1682 
1683       PetscCall(PetscLogHandlerGetEventPerfInfo(h, PETSC_DEFAULT, event, &event_info));
1684       if (event_info) event_info->errors[n] = error;
1685     }
1686   }
1687   PetscFunctionReturn(PETSC_SUCCESS);
1688 }
1689 
1690 /*@
1691   PetscLogEventGetId - Returns the event id when given the event name.
1692 
1693   Not Collective
1694 
1695   Input Parameter:
1696 . name - The event name
1697 
1698   Output Parameter:
1699 . event - The event, or -1 if no event with that name exists
1700 
1701   Level: intermediate
1702 
1703 .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1704 @*/
1705 PetscErrorCode PetscLogEventGetId(const char name[], PetscLogEvent *event)
1706 {
1707   PetscLogState state;
1708 
1709   PetscFunctionBegin;
1710   *event = -1;
1711   PetscCall(PetscLogGetState(&state));
1712   if (state) PetscCall(PetscLogStateGetEventFromName(state, name, event));
1713   PetscFunctionReturn(PETSC_SUCCESS);
1714 }
1715 
1716 /*@
1717   PetscLogEventGetName - Returns the event name when given the event id.
1718 
1719   Not Collective
1720 
1721   Input Parameter:
1722 . event - The event
1723 
1724   Output Parameter:
1725 . name - The event name
1726 
1727   Level: intermediate
1728 
1729 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
1730 @*/
1731 PetscErrorCode PetscLogEventGetName(PetscLogEvent event, const char *name[])
1732 {
1733   PetscLogEventInfo event_info;
1734   PetscLogState     state;
1735 
1736   PetscFunctionBegin;
1737   *name = NULL;
1738   PetscCall(PetscLogGetState(&state));
1739   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
1740   PetscCall(PetscLogStateEventGetInfo(state, event, &event_info));
1741   *name = event_info.name;
1742   PetscFunctionReturn(PETSC_SUCCESS);
1743 }
1744 
1745 /*@
1746   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.
1747 
1748   Not collective
1749 
1750   Level: advanced
1751 
1752   Notes:
1753   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()`).
1754 
1755   Other log handlers (such as the nested handler, `PetscLogNestedBegin()`) will ignore this function.
1756 
1757 .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsResume()`, `PetscLogGetDefaultHandler()`
1758 @*/
1759 PetscErrorCode PetscLogEventsPause(void)
1760 {
1761   PetscFunctionBegin;
1762   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1763     PetscLogHandler h = PetscLogHandlers[i].handler;
1764 
1765     if (h) PetscCall(PetscLogHandlerEventsPause(h));
1766   }
1767   PetscFunctionReturn(PETSC_SUCCESS);
1768 }
1769 
1770 /*@
1771   PetscLogEventsResume - Return logging to normal behavior after it was paused with `PetscLogEventsPause()`.
1772 
1773   Not collective
1774 
1775   Level: advanced
1776 
1777 .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsPause()`, `PetscLogGetDefaultHandler()`
1778 @*/
1779 PetscErrorCode PetscLogEventsResume(void)
1780 {
1781   PetscFunctionBegin;
1782   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
1783     PetscLogHandler h = PetscLogHandlers[i].handler;
1784 
1785     if (h) PetscCall(PetscLogHandlerEventsResume(h));
1786   }
1787   PetscFunctionReturn(PETSC_SUCCESS);
1788 }
1789 
1790 /*------------------------------------------------ Class Functions --------------------------------------------------*/
1791 
1792 /*MC
1793    PetscLogObjectCreate - Log the creation of a `PetscObject`
1794 
1795    Synopsis:
1796    #include <petsclog.h>
1797    PetscErrorCode PetscLogObjectCreate(PetscObject h)
1798 
1799    Not Collective
1800 
1801    Input Parameters:
1802 .  h - A `PetscObject`
1803 
1804    Level: developer
1805 
1806    Developer Note:
1807      Called internally by PETSc when creating objects: users do not need to call this directly.
1808      Notification of the object creation is sent to each `PetscLogHandler` that is running.
1809 
1810 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectDestroy()`
1811 M*/
1812 
1813 /*MC
1814    PetscLogObjectDestroy - Logs the destruction of a `PetscObject`
1815 
1816    Synopsis:
1817    #include <petsclog.h>
1818    PetscErrorCode PetscLogObjectDestroy(PetscObject h)
1819 
1820    Not Collective
1821 
1822    Input Parameters:
1823 .  h - A `PetscObject`
1824 
1825    Level: developer
1826 
1827    Developer Note:
1828      Called internally by PETSc when destroying objects: users do not need to call this directly.
1829      Notification of the object creation is sent to each `PetscLogHandler` that is running.
1830 
1831 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogObjectCreate()`
1832 M*/
1833 
1834 /*@
1835   PetscLogClassGetClassId - Returns the `PetscClassId` when given the class name.
1836 
1837   Not Collective
1838 
1839   Input Parameter:
1840 . name - The class name
1841 
1842   Output Parameter:
1843 . classid - The `PetscClassId` id, or -1 if no class with that name exists
1844 
1845   Level: intermediate
1846 
1847 .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1848 @*/
1849 PetscErrorCode PetscLogClassGetClassId(const char name[], PetscClassId *classid)
1850 {
1851   PetscLogClass     log_class;
1852   PetscLogClassInfo class_info;
1853   PetscLogState     state;
1854 
1855   PetscFunctionBegin;
1856   *classid = -1;
1857   PetscCall(PetscLogGetState(&state));
1858   if (!state) PetscFunctionReturn(PETSC_SUCCESS);
1859   PetscCall(PetscLogStateGetClassFromName(state, name, &log_class));
1860   if (log_class < 0) {
1861     *classid = -1;
1862     PetscFunctionReturn(PETSC_SUCCESS);
1863   }
1864   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
1865   *classid = class_info.classid;
1866   PetscFunctionReturn(PETSC_SUCCESS);
1867 }
1868 
1869 /*@C
1870   PetscLogClassIdGetName - Returns a `PetscClassId`'s name.
1871 
1872   Not Collective
1873 
1874   Input Parameter:
1875 . classid - A `PetscClassId`
1876 
1877   Output Parameter:
1878 . name - The class name
1879 
1880   Level: intermediate
1881 
1882 .seealso: [](ch_profiling), `PetscLogClassRegister()`, `PetscLogClassBegin()`, `PetscLogClassEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadClass()`
1883 @*/
1884 PetscErrorCode PetscLogClassIdGetName(PetscClassId classid, const char **name)
1885 {
1886   PetscLogClass     log_class;
1887   PetscLogClassInfo class_info;
1888   PetscLogState     state;
1889 
1890   PetscFunctionBegin;
1891   PetscCall(PetscLogGetState(&state));
1892   PetscCall(PetscLogStateGetClassFromClassId(state, classid, &log_class));
1893   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
1894   *name = class_info.name;
1895   PetscFunctionReturn(PETSC_SUCCESS);
1896 }
1897 
1898 /*------------------------------------------------ Output Functions -------------------------------------------------*/
1899 /*@
1900   PetscLogDump - Dumps logs of objects to a file. This file is intended to
1901   be read by bin/petscview. This program no longer exists.
1902 
1903   Collective on `PETSC_COMM_WORLD`
1904 
1905   Input Parameter:
1906 . sname - an optional file name
1907 
1908   Example Usage:
1909 .vb
1910   PetscInitialize(...);
1911   PetscLogDefaultBegin();
1912   // ... code ...
1913   PetscLogDump(filename);
1914   PetscFinalize();
1915 .ve
1916 
1917   Level: advanced
1918 
1919   Note:
1920   The default file name is Log.<rank> where <rank> is the MPI process rank. If no name is specified,
1921   this file will be used.
1922 
1923 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogView()`, `PetscLogGetDefaultHandler()`
1924 @*/
1925 PetscErrorCode PetscLogDump(const char sname[])
1926 {
1927   PetscLogHandler handler;
1928 
1929   PetscFunctionBegin;
1930   PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
1931   PetscCall(PetscLogHandlerDump(handler, sname));
1932   PetscFunctionReturn(PETSC_SUCCESS);
1933 }
1934 
1935 /*@
1936   PetscLogMPEDump - Dumps the MPE logging info to file for later use with Jumpshot.
1937 
1938   Collective on `PETSC_COMM_WORLD`
1939 
1940   Input Parameter:
1941 . sname - filename for the MPE logfile
1942 
1943   Level: advanced
1944 
1945 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogMPEBegin()`
1946 @*/
1947 PetscErrorCode PetscLogMPEDump(const char sname[])
1948 {
1949   PetscFunctionBegin;
1950   #if defined(PETSC_HAVE_MPE)
1951   if (PetscBeganMPE) {
1952     char name[PETSC_MAX_PATH_LEN];
1953 
1954     PetscCall(PetscInfo(0, "Finalizing MPE.\n"));
1955     if (sname) {
1956       PetscCall(PetscStrncpy(name, sname, sizeof(name)));
1957     } else {
1958       PetscCall(PetscGetProgramName(name, sizeof(name)));
1959     }
1960     PetscCall(MPE_Finish_log(name));
1961   } else {
1962     PetscCall(PetscInfo(0, "Not finalizing MPE (not started by PETSc).\n"));
1963   }
1964   #else
1965   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
1966   #endif
1967   PetscFunctionReturn(PETSC_SUCCESS);
1968 }
1969 
1970 /*@
1971   PetscLogView - Prints a summary of the logging.
1972 
1973   Collective
1974 
1975   Input Parameter:
1976 . viewer - an ASCII viewer
1977 
1978   Options Database Keys:
1979 + -log_view [:filename]                    - Prints summary of log information
1980 . -log_view :filename.py:ascii_info_detail - Saves logging information from each process as a Python file
1981 . -log_view :filename.xml:ascii_xml        - Saves a summary of the logging information in a nested format (see below for how to view it)
1982 . -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)
1983 . -log_view_memory                         - Also display memory usage in each event
1984 . -log_view_gpu_time                       - Also display time in each event for GPU kernels (Note this may slow the computation)
1985 . -log_all                                 - Saves a file Log.rank for each MPI rank with details of each step of the computation
1986 - -log_trace [filename]                    - Displays a trace of what each process is doing
1987 
1988   Level: beginner
1989 
1990   Notes:
1991   It is possible to control the logging programmatically but we recommend using the options database approach whenever possible
1992   By default the summary is printed to stdout.
1993 
1994   Before calling this routine you must have called either PetscLogDefaultBegin() or PetscLogNestedBegin()
1995 
1996   If PETSc is configured with --with-logging=0 then this functionality is not available
1997 
1998   To view the nested XML format filename.xml first copy  ${PETSC_DIR}/share/petsc/xml/performance_xml2html.xsl to the current
1999   directory then open filename.xml with your browser. Specific notes for certain browsers
2000 .vb
2001     Firefox and Internet explorer - simply open the file
2002     Google Chrome - you must start up Chrome with the option --allow-file-access-from-files
2003     Safari - see https://ccm.net/faq/36342-safari-how-to-enable-local-file-access
2004 .ve
2005   or one can use the package <http://xmlsoft.org/XSLT/xsltproc2.html> to translate the xml file to html and then open it with
2006   your browser.
2007   Alternatively, use the script ${PETSC_DIR}/lib/petsc/bin/petsc-performance-view to automatically open a new browser
2008   window and render the XML log file contents.
2009 
2010   The nested XML format was kindly donated by Koos Huijssen and Christiaan M. Klaij  MARITIME  RESEARCH  INSTITUTE  NETHERLANDS
2011 
2012   The Flame Graph output can be visualised using either the original Flame Graph script <https://github.com/brendangregg/FlameGraph>
2013   or using speedscope <https://www.speedscope.app>.
2014   Old XML profiles may be converted into this format using the script ${PETSC_DIR}/lib/petsc/bin/xml2flamegraph.py.
2015 
2016 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogDump()`
2017 @*/
2018 PetscErrorCode PetscLogView(PetscViewer viewer)
2019 {
2020   PetscBool         isascii;
2021   PetscViewerFormat format;
2022   int               stage;
2023   PetscLogState     state;
2024   PetscIntStack     temp_stack;
2025   PetscLogHandler   handler;
2026   PetscBool         is_empty;
2027 
2028   PetscFunctionBegin;
2029   PetscCall(PetscLogGetState(&state));
2030   /* Pop off any stages the user forgot to remove */
2031   PetscCall(PetscIntStackCreate(&temp_stack));
2032   PetscCall(PetscLogStateGetCurrentStage(state, &stage));
2033   while (stage >= 0) {
2034     PetscCall(PetscLogStagePop());
2035     PetscCall(PetscIntStackPush(temp_stack, stage));
2036     PetscCall(PetscLogStateGetCurrentStage(state, &stage));
2037   }
2038   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2039   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Currently can only view logging to ASCII");
2040   PetscCall(PetscViewerGetFormat(viewer, &format));
2041   if (format == PETSC_VIEWER_ASCII_XML || format == PETSC_VIEWER_ASCII_FLAMEGRAPH) {
2042     PetscCall(PetscLogGetHandler(PETSCLOGHANDLERNESTED, &handler));
2043     PetscCall(PetscLogHandlerView(handler, viewer));
2044   } else {
2045     PetscCall(PetscLogGetHandler(PETSCLOGHANDLERDEFAULT, &handler));
2046     PetscCall(PetscLogHandlerView(handler, viewer));
2047   }
2048   PetscCall(PetscIntStackEmpty(temp_stack, &is_empty));
2049   while (!is_empty) {
2050     PetscCall(PetscIntStackPop(temp_stack, &stage));
2051     PetscCall(PetscLogStagePush(stage));
2052     PetscCall(PetscIntStackEmpty(temp_stack, &is_empty));
2053   }
2054   PetscCall(PetscIntStackDestroy(temp_stack));
2055   PetscFunctionReturn(PETSC_SUCCESS);
2056 }
2057 
2058 /*@C
2059   PetscLogViewFromOptions - Processes command line options to determine if/how a `PetscLog` is to be viewed.
2060 
2061   Collective on `PETSC_COMM_WORLD`
2062 
2063   Level: developer
2064 
2065 .seealso: [](ch_profiling), `PetscLogView()`
2066 @*/
2067 PetscErrorCode PetscLogViewFromOptions(void)
2068 {
2069   PetscInt          n_max = PETSC_LOG_VIEW_FROM_OPTIONS_MAX;
2070   PetscViewer       viewers[PETSC_LOG_VIEW_FROM_OPTIONS_MAX];
2071   PetscViewerFormat formats[PETSC_LOG_VIEW_FROM_OPTIONS_MAX];
2072   PetscBool         flg;
2073 
2074   PetscFunctionBegin;
2075   PetscCall(PetscOptionsCreateViewers(PETSC_COMM_WORLD, NULL, NULL, "-log_view", &n_max, viewers, formats, &flg));
2076   /*
2077      PetscLogHandlerView_Default_Info() wants to be sure that the only objects still around are these viewers, so keep track of how many there are
2078    */
2079   PetscLogNumViewersCreated = n_max;
2080   for (PetscInt i = 0; i < n_max; i++) {
2081     PetscInt refct;
2082 
2083     PetscCall(PetscViewerPushFormat(viewers[i], formats[i]));
2084     PetscCall(PetscLogView(viewers[i]));
2085     PetscCall(PetscViewerPopFormat(viewers[i]));
2086     PetscCall(PetscObjectGetReference((PetscObject)viewers[i], &refct));
2087     PetscCall(PetscViewerDestroy(&viewers[i]));
2088     if (refct == 1) PetscLogNumViewersDestroyed++;
2089   }
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