xref: /petsc/src/sys/logging/plog.c (revision 2611ad710242b3c70d66651ef7e40f9450d305e2)
1 
2 /*
3       PETSc code to log object creation and destruction and PETSc events.
4 
5       This provides the public API used by the rest of PETSc and by users.
6 
7       These routines use a private API that is not used elsewhere in PETSc and is not
8       accessible to users. The private API is defined in logimpl.h and the utils directory.
9 
10 */
11 #include <petsc/private/logimpl.h> /*I    "petscsys.h"   I*/
12 #include <petsc/private/loghandlerimpl.h>
13 #include <petsctime.h>
14 #include <petscviewer.h>
15 #include <petscdevice.h>
16 #include <petsc/private/deviceimpl.h>
17 #if defined(PETSC_HAVE_TAU_PERFSTUBS)
18   #include <../src/sys/perfstubs/timer.h>
19 #endif
20 
21 #if defined(PETSC_HAVE_THREADSAFETY)
22 
23 PetscInt           petsc_log_gid = -1; /* Global threadId counter */
24 PETSC_TLS PetscInt petsc_log_tid = -1; /* Local threadId */
25 
26 /* shared variables */
27 PetscSpinlock  PetscLogSpinLock;
28 PetscHMapEvent eventInfoMap_th = NULL;
29 
30 PetscInt PetscLogGetTid(void)
31 {
32   if (petsc_log_tid < 0) {
33     PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
34     petsc_log_tid = ++petsc_log_gid;
35     PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
36   }
37   return petsc_log_tid;
38 }
39 
40 #endif
41 
42 PetscLogEvent PETSC_LARGEST_EVENT = PETSC_EVENT;
43 
44 /* Global counters */
45 PetscLogDouble petsc_BaseTime        = 0.0;
46 PetscLogDouble petsc_TotalFlops      = 0.0; /* The number of flops */
47 PetscLogDouble petsc_send_ct         = 0.0; /* The number of sends */
48 PetscLogDouble petsc_recv_ct         = 0.0; /* The number of receives */
49 PetscLogDouble petsc_send_len        = 0.0; /* The total length of all sent messages */
50 PetscLogDouble petsc_recv_len        = 0.0; /* The total length of all received messages */
51 PetscLogDouble petsc_isend_ct        = 0.0; /* The number of immediate sends */
52 PetscLogDouble petsc_irecv_ct        = 0.0; /* The number of immediate receives */
53 PetscLogDouble petsc_isend_len       = 0.0; /* The total length of all immediate send messages */
54 PetscLogDouble petsc_irecv_len       = 0.0; /* The total length of all immediate receive messages */
55 PetscLogDouble petsc_wait_ct         = 0.0; /* The number of waits */
56 PetscLogDouble petsc_wait_any_ct     = 0.0; /* The number of anywaits */
57 PetscLogDouble petsc_wait_all_ct     = 0.0; /* The number of waitalls */
58 PetscLogDouble petsc_sum_of_waits_ct = 0.0; /* The total number of waits */
59 PetscLogDouble petsc_allreduce_ct    = 0.0; /* The number of reductions */
60 PetscLogDouble petsc_gather_ct       = 0.0; /* The number of gathers and gathervs */
61 PetscLogDouble petsc_scatter_ct      = 0.0; /* The number of scatters and scattervs */
62 
63 /* Thread Local storage */
64 PETSC_TLS PetscLogDouble petsc_TotalFlops_th      = 0.0;
65 PETSC_TLS PetscLogDouble petsc_send_ct_th         = 0.0;
66 PETSC_TLS PetscLogDouble petsc_recv_ct_th         = 0.0;
67 PETSC_TLS PetscLogDouble petsc_send_len_th        = 0.0;
68 PETSC_TLS PetscLogDouble petsc_recv_len_th        = 0.0;
69 PETSC_TLS PetscLogDouble petsc_isend_ct_th        = 0.0;
70 PETSC_TLS PetscLogDouble petsc_irecv_ct_th        = 0.0;
71 PETSC_TLS PetscLogDouble petsc_isend_len_th       = 0.0;
72 PETSC_TLS PetscLogDouble petsc_irecv_len_th       = 0.0;
73 PETSC_TLS PetscLogDouble petsc_wait_ct_th         = 0.0;
74 PETSC_TLS PetscLogDouble petsc_wait_any_ct_th     = 0.0;
75 PETSC_TLS PetscLogDouble petsc_wait_all_ct_th     = 0.0;
76 PETSC_TLS PetscLogDouble petsc_sum_of_waits_ct_th = 0.0;
77 PETSC_TLS PetscLogDouble petsc_allreduce_ct_th    = 0.0;
78 PETSC_TLS PetscLogDouble petsc_gather_ct_th       = 0.0;
79 PETSC_TLS PetscLogDouble petsc_scatter_ct_th      = 0.0;
80 
81 PetscLogDouble petsc_ctog_ct        = 0.0; /* The total number of CPU to GPU copies */
82 PetscLogDouble petsc_gtoc_ct        = 0.0; /* The total number of GPU to CPU copies */
83 PetscLogDouble petsc_ctog_sz        = 0.0; /* The total size of CPU to GPU copies */
84 PetscLogDouble petsc_gtoc_sz        = 0.0; /* The total size of GPU to CPU copies */
85 PetscLogDouble petsc_ctog_ct_scalar = 0.0; /* The total number of CPU to GPU copies */
86 PetscLogDouble petsc_gtoc_ct_scalar = 0.0; /* The total number of GPU to CPU copies */
87 PetscLogDouble petsc_ctog_sz_scalar = 0.0; /* The total size of CPU to GPU copies */
88 PetscLogDouble petsc_gtoc_sz_scalar = 0.0; /* The total size of GPU to CPU copies */
89 PetscLogDouble petsc_gflops         = 0.0; /* The flops done on a GPU */
90 PetscLogDouble petsc_gtime          = 0.0; /* The time spent on a GPU */
91 
92 PETSC_TLS PetscLogDouble petsc_ctog_ct_th        = 0.0;
93 PETSC_TLS PetscLogDouble petsc_gtoc_ct_th        = 0.0;
94 PETSC_TLS PetscLogDouble petsc_ctog_sz_th        = 0.0;
95 PETSC_TLS PetscLogDouble petsc_gtoc_sz_th        = 0.0;
96 PETSC_TLS PetscLogDouble petsc_ctog_ct_scalar_th = 0.0;
97 PETSC_TLS PetscLogDouble petsc_gtoc_ct_scalar_th = 0.0;
98 PETSC_TLS PetscLogDouble petsc_ctog_sz_scalar_th = 0.0;
99 PETSC_TLS PetscLogDouble petsc_gtoc_sz_scalar_th = 0.0;
100 PETSC_TLS PetscLogDouble petsc_gflops_th         = 0.0;
101 PETSC_TLS PetscLogDouble petsc_gtime_th          = 0.0;
102 
103 PetscBool PetscLogMemory = PETSC_FALSE;
104 PetscBool PetscLogSyncOn = PETSC_FALSE;
105 
106 PetscBool PetscLogGpuTimeFlag = PETSC_FALSE;
107 
108 PetscLogState petsc_log_state = NULL;
109 
110 #define PETSC_LOG_HANDLER_HOT_BLANK \
111   { \
112     NULL, NULL, NULL, NULL, NULL, NULL \
113   }
114 
115 PetscLogHandlerHot PetscLogHandlers[PETSC_LOG_HANDLER_MAX] = {
116   PETSC_LOG_HANDLER_HOT_BLANK,
117   PETSC_LOG_HANDLER_HOT_BLANK,
118   PETSC_LOG_HANDLER_HOT_BLANK,
119   PETSC_LOG_HANDLER_HOT_BLANK,
120 };
121 
122 #undef PETSC_LOG_HANDLERS_HOT_BLANK
123 
124 #if defined(PETSC_USE_LOG)
125   #include <petscmachineinfo.h>
126   #include <petscconfiginfo.h>
127 
128 /* used in the MPI_XXX() count macros in petsclog.h */
129 
130 /* Action and object logging variables */
131 Action   *petsc_actions    = NULL;
132 Object   *petsc_objects    = NULL;
133 PetscBool petsc_logActions = PETSC_FALSE;
134 PetscBool petsc_logObjects = PETSC_FALSE;
135 int       petsc_numActions = 0, petsc_maxActions = 100;
136 int       petsc_numObjects = 0, petsc_maxObjects = 100;
137 int       petsc_numObjectsDestroyed = 0;
138 
139   #include <../src/sys/logging/handler/impls/default/logdefault.h>
140 
141   #if defined(PETSC_HAVE_THREADSAFETY)
142 PetscErrorCode PetscAddLogDouble(PetscLogDouble *tot, PetscLogDouble *tot_th, PetscLogDouble tmp)
143 {
144   *tot_th += tmp;
145   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
146   *tot += tmp;
147   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
148   return PETSC_SUCCESS;
149 }
150 
151 PetscErrorCode PetscAddLogDoubleCnt(PetscLogDouble *cnt, PetscLogDouble *tot, PetscLogDouble *cnt_th, PetscLogDouble *tot_th, PetscLogDouble tmp)
152 {
153   *cnt_th = *cnt_th + 1;
154   *tot_th += tmp;
155   PetscCall(PetscSpinlockLock(&PetscLogSpinLock));
156   *tot += (PetscLogDouble)(tmp);
157   *cnt += *cnt + 1;
158   PetscCall(PetscSpinlockUnlock(&PetscLogSpinLock));
159   return PETSC_SUCCESS;
160 }
161 
162   #endif
163 
164 static PetscErrorCode PetscLogTryGetHandler(PetscLogHandlerType type, PetscLogHandler *handler)
165 {
166   PetscFunctionBegin;
167   PetscAssertPointer(handler, 2);
168   *handler = NULL;
169   for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
170     PetscLogHandler h = PetscLogHandlers[i].handler;
171     if (h) {
172       PetscBool match;
173 
174       PetscCall(PetscObjectTypeCompare((PetscObject)h, type, &match));
175       if (match) {
176         *handler = PetscLogHandlers[i].handler;
177         PetscFunctionReturn(PETSC_SUCCESS);
178       }
179     }
180   }
181   PetscFunctionReturn(PETSC_SUCCESS);
182 }
183 
184 /*@
185   PetscLogGetState - Get the `PetscLogState` for PETSc's global logging, used
186   by all default log handlers (`PetscLogDefaultBegin()`,
187   `PetscLogNestedBegin()`, `PetscLogTraceBegin()`, `PetscLogMPEBegin()`,
188   `PetscLogPerfstubsBegin()`).
189 
190   Collective on `PETSC_COMM_WORLD`
191 
192   Output Parameter:
193 . state - The `PetscLogState` changed by registrations (such as `PetscLogEventRegister()`) and actions (such as `PetscLogEventBegin()` or `PetscLogStagePush()`)
194 
195   Level: developer
196 
197 .seealso: [](ch_profiling), `PetscLogState`
198 @*/
199 PetscErrorCode PetscLogGetState(PetscLogState *state)
200 {
201   PetscFunctionBegin;
202   PetscAssertPointer(state, 1);
203   if (!petsc_log_state) {
204     fprintf(stderr, "PETSC ERROR: Logging has not been enabled.\nYou might have forgotten to call PetscInitialize().\n");
205     PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_SUP);
206   }
207   *state = petsc_log_state;
208   PetscFunctionReturn(PETSC_SUCCESS);
209 }
210 
211 /* Logging functions */
212 PetscErrorCode (*PetscLogPHC)(PetscObject)                                                            = NULL;
213 PetscErrorCode (*PetscLogPHD)(PetscObject)                                                            = NULL;
214 PetscErrorCode (*PetscLogPLB)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject) = NULL;
215 PetscErrorCode (*PetscLogPLE)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject) = NULL;
216 
217 static PetscErrorCode PetscLogHandlerCopyToHot(PetscLogHandler h, PetscLogHandlerHot *hot)
218 {
219   PetscFunctionBegin;
220   hot->handler       = h;
221   hot->eventBegin    = h->ops->eventbegin;
222   hot->eventEnd      = h->ops->eventend;
223   hot->eventSync     = h->ops->eventsync;
224   hot->objectCreate  = h->ops->objectcreate;
225   hot->objectDestroy = h->ops->objectdestroy;
226   PetscFunctionReturn(PETSC_SUCCESS);
227 }
228 
229 /*@
230   PetscLogHandlerStart - Connect a log handler to PETSc's global logging stream and state.
231 
232   Logically collective
233 
234   Input Parameters:
235 . h - a `PetscLogHandler`
236 
237   Level: developer
238 
239   Notes:
240 
241   Users should only need this if they create their own log handlers: handlers that are started
242   from the command line (such as `-log_view` and `-log_trace`) or from a function like
243   `PetscLogNestedBegin()` will automatically be started.
244 
245   There is a limit of `PESC_LOG_HANDLER_MAX` handlers that can be active at one time.
246 
247   To disconnect a handler from the global stream call `PetscLogHandlerStop()`.
248 
249   When a log handler is started, stages that have already been pushed with `PetscLogStagePush()`,
250   will be pushed for the new log handler, but it will not be informed of any events that are
251   in progress.  It is recommended to start any user-defined log handlers immediately following
252   before any user-defined stages are pushed.
253 
254 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogState`, `PetscLogHandlerStop()`
255 @*/
256 PetscErrorCode PetscLogHandlerStart(PetscLogHandler h)
257 {
258   PetscFunctionBegin;
259   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
260     if (PetscLogHandlers[i].handler == h) PetscFunctionReturn(PETSC_SUCCESS);
261   }
262   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
263     if (PetscLogHandlers[i].handler == NULL) {
264       PetscCall(PetscObjectReference((PetscObject)h));
265       PetscCall(PetscLogHandlerCopyToHot(h, &PetscLogHandlers[i]));
266       if (petsc_log_state) {
267         PetscLogStage stack_height;
268         PetscIntStack orig_stack, temp_stack;
269 
270         PetscCall(PetscLogHandlerSetState(h, petsc_log_state));
271         stack_height = petsc_log_state->stage_stack->top + 1;
272         PetscCall(PetscIntStackCreate(&temp_stack));
273         orig_stack                     = petsc_log_state->stage_stack;
274         petsc_log_state->stage_stack   = temp_stack;
275         petsc_log_state->current_stage = -1;
276         for (int s = 0; s < stack_height; s++) {
277           PetscLogStage stage = (PetscLogStage)orig_stack->stack[s];
278           PetscCall(PetscLogHandlerStagePush(h, stage));
279           PetscCall(PetscIntStackPush(temp_stack, stage));
280           petsc_log_state->current_stage = stage;
281         }
282         PetscCall(PetscIntStackDestroy(temp_stack));
283         petsc_log_state->stage_stack = orig_stack;
284       }
285       PetscFunctionReturn(PETSC_SUCCESS);
286     }
287   }
288   SETERRQ(PetscObjectComm((PetscObject)h), PETSC_ERR_ARG_WRONGSTATE, "%d log handlers already started, cannot start another", PETSC_LOG_HANDLER_MAX);
289   PetscFunctionReturn(PETSC_SUCCESS);
290 }
291 
292 /*@
293   PetscLogHandlerStop - Disconnect a log handler from PETSc's global logging stream.
294 
295   Logically collective
296 
297   Input Parameters:
298 . h - a `PetscLogHandler`
299 
300   Level: developer
301 
302   Note:
303   After `PetscLogHandlerStop()`, the handler can still access the global logging state
304   with `PetscLogHandlerGetState()`, so that it can access the registry when post-processing
305   (for instance, in `PetscLogHandlerView()`),
306 
307   When a log handler is stopped, the remaining stages will be popped before it is
308   disconnected from the log stream.
309 
310 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogState`, `PetscLogHandlerStart()`
311 @*/
312 PetscErrorCode PetscLogHandlerStop(PetscLogHandler h)
313 {
314   PetscFunctionBegin;
315   for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
316     if (PetscLogHandlers[i].handler == h) {
317       if (petsc_log_state) {
318         PetscLogState state;
319         PetscLogStage stack_height;
320         PetscIntStack orig_stack, temp_stack;
321 
322         PetscCall(PetscLogHandlerGetState(h, &state));
323         PetscCheck(state == petsc_log_state, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "Called PetscLogHandlerStop() for a PetscLogHander that was not started.");
324         stack_height = petsc_log_state->stage_stack->top + 1;
325         PetscCall(PetscIntStackCreate(&temp_stack));
326         orig_stack                   = petsc_log_state->stage_stack;
327         petsc_log_state->stage_stack = temp_stack;
328         for (int s = 0; s < stack_height; s++) {
329           PetscLogStage stage = (PetscLogStage)orig_stack->stack[s];
330 
331           PetscCall(PetscIntStackPush(temp_stack, stage));
332         }
333         for (int s = 0; s < stack_height; s++) {
334           PetscLogStage stage;
335           PetscBool     empty;
336 
337           PetscCall(PetscIntStackPop(temp_stack, &stage));
338           PetscCall(PetscIntStackEmpty(temp_stack, &empty));
339           if (!empty) {
340             PetscCall(PetscIntStackTop(temp_stack, &petsc_log_state->current_stage));
341           } else petsc_log_state->current_stage = -1;
342           PetscCall(PetscLogHandlerStagePop(h, stage));
343         }
344         PetscCall(PetscIntStackDestroy(temp_stack));
345         petsc_log_state->stage_stack = orig_stack;
346         PetscCall(PetscIntStackTop(petsc_log_state->stage_stack, &petsc_log_state->current_stage));
347       }
348       PetscCall(PetscArrayzero(&PetscLogHandlers[i], 1));
349       PetscCall(PetscObjectDereference((PetscObject)h));
350     }
351   }
352   PetscFunctionReturn(PETSC_SUCCESS);
353 }
354 /*@C
355   PetscLogSet - Sets the logging functions called at the beginning and ending of every event.
356 
357   Not Collective
358 
359   Input Parameters:
360 + b - The function called at beginning of event
361 - e - The function called at end of event
362 
363   Level: developer
364 
365   Developer Notes:
366   The default loggers are `PetscLogEventBeginDefault()` and `PetscLogEventEndDefault()`.
367 
368 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogDefaultBegin()`, `PetscLogAllBegin()`, `PetscLogTraceBegin()`, `PetscLogEventBeginDefault()`, `PetscLogEventEndDefault()`
369 @*/
370 PetscErrorCode PetscLogSet(PetscErrorCode (*b)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject), PetscErrorCode (*e)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject))
371 {
372   PetscFunctionBegin;
373   PetscLogPLB = b;
374   PetscLogPLE = e;
375   PetscFunctionReturn(PETSC_SUCCESS);
376 }
377 
378 /*@C
379   PetscLogIsActive - Check if logging is currently in progress.
380 
381   Not Collective
382 
383   Output Parameter:
384 . isActive - `PETSC_TRUE` if logging is in progress, `PETSC_FALSE` otherwise
385 
386   Level: beginner
387 
388 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogAllBegin()`, `PetscLogSet()`
389 @*/
390 PetscErrorCode PetscLogIsActive(PetscBool *isActive)
391 {
392   PetscFunctionBegin;
393   *isActive = (PetscLogPLB && PetscLogPLE) ? PETSC_TRUE : PETSC_FALSE;
394   PetscFunctionReturn(PETSC_SUCCESS);
395 }
396 
397 static PetscErrorCode PetscLogTypeBegin(PetscLogHandlerType type)
398 {
399   PetscLogHandler handler;
400 
401   PetscFunctionBegin;
402   PetscCall(PetscLogTryGetHandler(type, &handler));
403   if (handler) PetscFunctionReturn(PETSC_SUCCESS);
404   PetscCall(PetscLogHandlerCreate(PETSC_COMM_WORLD, &handler));
405   PetscCall(PetscLogHandlerSetType(handler, type));
406   PetscCall(PetscLogHandlerStart(handler));
407   PetscCall(PetscLogHandlerDestroy(&handler));
408   PetscFunctionReturn(PETSC_SUCCESS);
409 }
410 
411 /*@C
412   PetscLogDefaultBegin - Turns on logging of objects and events using the default logging functions `PetscLogEventBeginDefault()` and `PetscLogEventEndDefault()`. This logs flop
413   rates and object creation and should not slow programs down too much.
414   This routine may be called more than once.
415 
416   Logically Collective over `PETSC_COMM_WORLD`
417 
418   Options Database Key:
419 . -log_view [viewertype:filename:viewerformat] - Prints summary of flop and timing information to the
420                   screen (for code configured with --with-log=1 (which is the default))
421 
422   Example Usage:
423 .vb
424       PetscInitialize(...);
425       PetscLogDefaultBegin();
426        ... code ...
427       PetscLogView(viewer); or PetscLogDump();
428       PetscFinalize();
429 .ve
430 
431   Level: advanced
432 
433   Note:
434   `PetscLogView()` or `PetscLogDump()` actually cause the printing of
435   the logging information.
436 
437 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogAllBegin()`, `PetscLogView()`, `PetscLogTraceBegin()`
438 @*/
439 PetscErrorCode PetscLogDefaultBegin(void)
440 {
441   PetscFunctionBegin;
442   PetscCall(PetscLogSet(PetscLogEventBeginDefault, PetscLogEventEndDefault));
443   PetscFunctionReturn(PETSC_SUCCESS);
444 }
445 
446 /*@C
447   PetscLogAllBegin - Turns on extensive logging of objects and events. Logs
448   all events. This creates large log files and slows the program down.
449 
450   Logically Collective on `PETSC_COMM_WORLD`
451 
452   Options Database Key:
453 . -log_all - Prints extensive log information
454 
455   Example Usage:
456 .vb
457      PetscInitialize(...);
458      PetscLogAllBegin();
459      ... code ...
460      PetscLogDump(filename);
461      PetscFinalize();
462 .ve
463 
464   Level: advanced
465 
466   Note:
467   A related routine is `PetscLogDefaultBegin()` (with the options key -log_view), which is
468   intended for production runs since it logs only flop rates and object
469   creation (and shouldn't significantly slow the programs).
470 
471 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogDefaultBegin()`, `PetscLogTraceBegin()`
472 @*/
473 PetscErrorCode PetscLogAllBegin(void)
474 {
475   PetscFunctionBegin;
476   PetscCall(PetscLogSet(PetscLogEventBeginComplete, PetscLogEventEndComplete));
477   PetscFunctionReturn(PETSC_SUCCESS);
478 }
479 
480 /*@C
481   PetscLogTraceBegin - Activates trace logging.  Every time a PETSc event
482   begins or ends, the event name is printed.
483 
484   Logically Collective on `PETSC_COMM_WORLD`
485 
486   Input Parameter:
487 . file - The file to print trace in (e.g. stdout)
488 
489   Options Database Key:
490 . -log_trace [filename] - Activates `PetscLogTraceBegin()`
491 
492   Level: intermediate
493 
494   Notes:
495   `PetscLogTraceBegin()` prints the processor number, the execution time (sec),
496   then "Event begin:" or "Event end:" followed by the event name.
497 
498   `PetscLogTraceBegin()` allows tracing of all PETSc calls, which is useful
499   to determine where a program is hanging without running in the
500   debugger.  Can be used in conjunction with the -info option.
501 
502 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogAllBegin()`, `PetscLogView()`, `PetscLogDefaultBegin()`
503 @*/
504 PetscErrorCode PetscLogTraceBegin(FILE *file)
505 {
506   PetscFunctionBegin;
507   petsc_tracefile = file;
508 
509   PetscCall(PetscLogSet(PetscLogEventBeginTrace, PetscLogEventEndTrace));
510   PetscFunctionReturn(PETSC_SUCCESS);
511 }
512 
513 /*@C
514   PetscLogLegacyCallbacksBegin - Create and start a log handler from callbacks
515   matching the now deprecated function pointers `PetscLogPLB`, `PetscLogPLE`,
516   `PetscLogPHC`, `PetscLogPHD`.
517 
518   Logically Collective over `PETSC_COMM_WORLD`
519 
520   Input Parameters:
521 + PetscLogPLB - A callback that will be executed by `PetscLogEventBegin()` (or `NULL`)
522 . PetscLogPLE - A callback that will be executed by `PetscLogEventEnd()` (or `NULL`)
523 . PetscLogPHC - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)
524 - PetscLogPHD - A callback that will be executed by `PetscLogObjectCreate()` (or `NULL`)
525 
526   Calling sequence of `PetscLogPLB`:
527 + e  - a `PetscLogEvent` that is beginning
528 . _i - deprecated, unused
529 . o1 - a `PetscObject` associated with `e` (or `NULL`)
530 . o2 - a `PetscObject` associated with `e` (or `NULL`)
531 . o3 - a `PetscObject` associated with `e` (or `NULL`)
532 - o4 - a `PetscObject` associated with `e` (or `NULL`)
533 
534   Calling sequence of `PetscLogPLE`:
535 + e  - a `PetscLogEvent` that is beginning
536 . _i - deprecated, unused
537 . o1 - a `PetscObject` associated with `e` (or `NULL`)
538 . o2 - a `PetscObject` associated with `e` (or `NULL`)
539 . o3 - a `PetscObject` associated with `e` (or `NULL`)
540 - o4 - a `PetscObject` associated with `e` (or `NULL`)
541 
542   Calling sequence of `PetscLogPHC`:
543 . o - a `PetscObject` that has just been created
544 
545   Calling sequence of `PetscLogPHD`:
546 . o - a `PetscObject` that is about to be destroyed
547 
548   Level: advanced
549 
550   Notes:
551   This is for transitioning from the deprecated function `PetscLogSet()` and should not be used in new code.
552 
553   This should help migrate external log handlers to use `PetscLogHandler`, but
554   callbacks that depend on the deprecated `PetscLogStage` datatype will have to be
555   updated.
556 
557 .seealso: [](ch_profiling), `PetscLogHandler`, `PetscLogHandlerStart()`, `PetscLogState`
558 @*/
559 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))
560 {
561   PetscLogHandler handler;
562 
563   PetscFunctionBegin;
564   PetscCall(PetscLogHandlerCreateLegacy(PETSC_COMM_WORLD, PetscLogPLB, PetscLogPLE, PetscLogPHC, PetscLogPHD, &handler));
565   PetscCall(PetscLogHandlerStart(handler));
566   PetscCall(PetscLogHandlerDestroy(&handler));
567   PetscFunctionReturn(PETSC_SUCCESS);
568 }
569 
570   #if defined(PETSC_HAVE_MPE)
571     #include <mpe.h>
572 
573 PETSC_INTERN PetscErrorCode PetscLogHandlerCreate_MPE(MPI_Comm, PetscLogHandler *);
574 
575 static PetscBool PetscBeganMPE = PETSC_FALSE;
576 
577 PETSC_INTERN PetscErrorCode PetscLogEventBeginMPE(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject);
578 PETSC_INTERN PetscErrorCode PetscLogEventEndMPE(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject);
579   #endif
580 
581 /*@C
582   PetscLogMPEBegin - Turns on MPE logging of events. This creates large log files and slows the
583   program down.
584 
585   Collective over `PETSC_COMM_WORLD`
586 
587   Options Database Key:
588 . -log_mpe - Prints extensive log information
589 
590   Level: advanced
591 
592   Note:
593   A related routine is `PetscLogDefaultBegin()` (with the options key `-log_view`), which is
594   intended for production runs since it logs only flop rates and object creation (and should
595   not significantly slow the programs).
596 
597 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogDefaultBegin()`, `PetscLogAllBegin()`, `PetscLogEventActivate()`,
598           `PetscLogEventDeactivate()`
599 @*/
600 PetscErrorCode PetscLogMPEBegin(void)
601 {
602   PetscFunctionBegin;
603   #if defined(PETSC_HAVE_MPE)
604   /* Do MPE initialization */
605   if (!MPE_Initialized_logging()) { /* This function exists in mpich 1.1.2 and higher */
606     PetscCall(PetscInfo(0, "Initializing MPE.\n"));
607     PetscCall(MPE_Init_log());
608 
609     PetscBeganMPE = PETSC_TRUE;
610   } else {
611     PetscCall(PetscInfo(0, "MPE already initialized. Not attempting to reinitialize.\n"));
612   }
613   PetscCall(PetscLogSet(PetscLogEventBeginMPE, PetscLogEventEndMPE));
614   #else
615   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without MPE support, reconfigure with --with-mpe or --download-mpe");
616   #endif
617   PetscFunctionReturn(PETSC_SUCCESS);
618 }
619 
620   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
621     #include <../src/sys/perfstubs/timer.h>
622   #endif
623 
624 /*@C
625   PetscLogPerfstubsBegin - Turns on logging of events using the perfstubs interface.
626 
627   Collective over `PETSC_COMM_WORLD`
628 
629   Options Database Key:
630 . -log_perfstubs - use an external log handler through the perfstubs interface
631 
632   Level: advanced
633 
634 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogEventActivate()`
635 @*/
636 PetscErrorCode PetscLogPerfstubsBegin(void)
637 {
638   PetscFunctionBegin;
639   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
640   PetscCall(PetscLogTypeBegin(PETSC_LOG_HANDLER_PERFSTUBS));
641   #else
642   SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS, "PETSc was configured without perfstubs support, reconfigure with --with-tau-perfstubs");
643   #endif
644   PetscFunctionReturn(PETSC_SUCCESS);
645 }
646 
647 /*@
648   PetscLogActions - Determines whether actions are logged for the graphical viewer.
649 
650   Not Collective
651 
652   Input Parameter:
653 . flag - `PETSC_TRUE` if actions are to be logged
654 
655   Options Database Key:
656 . -log_exclude_actions - Turns off actions logging
657 
658   Level: intermediate
659 
660   Note:
661   Logging of actions continues to consume more memory as the program
662   runs. Long running programs should consider turning this feature off.
663 
664 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`
665 @*/
666 PetscErrorCode PetscLogActions(PetscBool flag)
667 {
668   PetscFunctionBegin;
669   petsc_logActions = flag;
670   PetscFunctionReturn(PETSC_SUCCESS);
671 }
672 
673 /*@
674   PetscLogObjects - Determines whether objects are logged for the graphical viewer.
675 
676   Not Collective
677 
678   Input Parameter:
679 . flag - `PETSC_TRUE` if objects are to be logged
680 
681   Options Database Key:
682 . -log_exclude_objects - Turns off objects logging
683 
684   Level: intermediate
685 
686   Note:
687   Logging of objects continues to consume more memory as the program
688   runs. Long running programs should consider turning this feature off.
689 
690 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`
691 @*/
692 PetscErrorCode PetscLogObjects(PetscBool flag)
693 {
694   PetscFunctionBegin;
695   petsc_logObjects = flag;
696   PetscFunctionReturn(PETSC_SUCCESS);
697 }
698 
699 /*------------------------------------------------ Stage Functions --------------------------------------------------*/
700 /*@C
701   PetscLogStageRegister - Attaches a character string name to a logging stage.
702 
703   Not Collective
704 
705   Input Parameter:
706 . sname - The name to associate with that stage
707 
708   Output Parameter:
709 . stage - The stage number
710 
711   Level: intermediate
712 
713 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStagePop()`
714 @*/
715 PetscErrorCode PetscLogStageRegister(const char sname[], PetscLogStage *stage)
716 {
717   PetscStageLog stageLog;
718   PetscLogEvent event;
719 
720   PetscFunctionBegin;
721   PetscCall(PetscLogGetStageLog(&stageLog));
722   PetscCall(PetscStageLogRegister(stageLog, sname, stage));
723   /* Copy events already changed in the main stage, this sucks */
724   PetscCall(PetscEventPerfLogEnsureSize(stageLog->stageInfo[*stage].eventLog, stageLog->eventLog->numEvents));
725   for (event = 0; event < stageLog->eventLog->numEvents; event++) PetscCall(PetscEventPerfInfoCopy(&stageLog->stageInfo[0].eventLog->eventInfo[event], &stageLog->stageInfo[*stage].eventLog->eventInfo[event]));
726   PetscCall(PetscClassPerfLogEnsureSize(stageLog->stageInfo[*stage].classLog, stageLog->classLog->numClasses));
727   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
728   if (perfstubs_initialized == PERFSTUBS_SUCCESS) PetscStackCallExternalVoid("ps_timer_create_", stageLog->stageInfo[*stage].timer = ps_timer_create_(sname));
729   #endif
730   PetscFunctionReturn(PETSC_SUCCESS);
731 }
732 
733 /*@C
734   PetscLogStagePush - This function pushes a stage on the logging stack. Events started and stopped until `PetscLogStagePop()` will be associated with the stage
735 
736   Not Collective
737 
738   Input Parameter:
739 . stage - The stage on which to log
740 
741   Example Usage:
742   If the option -log_view is used to run the program containing the
743   following code, then 2 sets of summary data will be printed during
744   PetscFinalize().
745 .vb
746       PetscInitialize(int *argc,char ***args,0,0);
747       [stage 0 of code]
748       PetscLogStagePush(1);
749       [stage 1 of code]
750       PetscLogStagePop();
751       PetscBarrier(...);
752       [more stage 0 of code]
753       PetscFinalize();
754 .ve
755 
756   Level: intermediate
757 
758   Note:
759   Use `PetscLogStageRegister()` to register a stage.
760 
761 .seealso: [](ch_profiling), `PetscLogStagePop()`, `PetscLogStageRegister()`, `PetscBarrier()`
762 @*/
763 PetscErrorCode PetscLogStagePush(PetscLogStage stage)
764 {
765   PetscStageLog stageLog;
766 
767   PetscFunctionBegin;
768   PetscCall(PetscLogGetStageLog(&stageLog));
769   PetscCall(PetscStageLogPush(stageLog, stage));
770   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
771   if (perfstubs_initialized == PERFSTUBS_SUCCESS && stageLog->stageInfo[stage].timer != NULL) PetscStackCallExternalVoid("ps_timer_start_", ps_timer_start_(stageLog->stageInfo[stage].timer));
772   #endif
773   PetscFunctionReturn(PETSC_SUCCESS);
774 }
775 
776 /*@C
777   PetscLogStagePop - This function pops a stage from the logging stack that was pushed with `PetscLogStagePush()`
778 
779   Not Collective
780 
781   Example Usage:
782   If the option -log_view is used to run the program containing the
783   following code, then 2 sets of summary data will be printed during
784   PetscFinalize().
785 .vb
786       PetscInitialize(int *argc,char ***args,0,0);
787       [stage 0 of code]
788       PetscLogStagePush(1);
789       [stage 1 of code]
790       PetscLogStagePop();
791       PetscBarrier(...);
792       [more stage 0 of code]
793       PetscFinalize();
794 .ve
795 
796   Level: intermediate
797 
798 .seealso: [](ch_profiling), `PetscLogStagePush()`, `PetscLogStageRegister()`, `PetscBarrier()`
799 @*/
800 PetscErrorCode PetscLogStagePop(void)
801 {
802   PetscStageLog stageLog;
803 
804   PetscFunctionBegin;
805   PetscCall(PetscLogGetStageLog(&stageLog));
806   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
807   if (perfstubs_initialized == PERFSTUBS_SUCCESS && stageLog->stageInfo[stageLog->curStage].timer != NULL) PetscStackCallExternalVoid("ps_timer_stop_", ps_timer_stop_(stageLog->stageInfo[stageLog->curStage].timer));
808   #endif
809   PetscCall(PetscStageLogPop(stageLog));
810   PetscFunctionReturn(PETSC_SUCCESS);
811 }
812 
813 /*@
814   PetscLogStageSetActive - Sets if a stage is used for `PetscLogEventBegin()` and `PetscLogEventEnd()`.
815 
816   Not Collective
817 
818   Input Parameters:
819 + stage    - The stage
820 - isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
821 
822   Level: intermediate
823 
824   Note:
825   If this is set to `PETSC_FALSE` the logging acts as if the stage did not exist
826 
827 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
828 @*/
829 PetscErrorCode PetscLogStageSetActive(PetscLogStage stage, PetscBool isActive)
830 {
831   PetscStageLog stageLog;
832 
833   PetscFunctionBegin;
834   PetscCall(PetscLogGetStageLog(&stageLog));
835   PetscCall(PetscStageLogSetActive(stageLog, stage, isActive));
836   PetscFunctionReturn(PETSC_SUCCESS);
837 }
838 
839 /*@
840   PetscLogStageGetActive - Checks if a stage is used for `PetscLogEventBegin()` and `PetscLogEventEnd()`.
841 
842   Not Collective
843 
844   Input Parameter:
845 . stage - The stage
846 
847   Output Parameter:
848 . isActive - The activity flag, `PETSC_TRUE` for logging, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
849 
850   Level: intermediate
851 
852 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
853 @*/
854 PetscErrorCode PetscLogStageGetActive(PetscLogStage stage, PetscBool *isActive)
855 {
856   PetscStageLog stageLog;
857 
858   PetscFunctionBegin;
859   PetscCall(PetscLogGetStageLog(&stageLog));
860   PetscCall(PetscStageLogGetActive(stageLog, stage, isActive));
861   PetscFunctionReturn(PETSC_SUCCESS);
862 }
863 
864 /*@
865   PetscLogStageSetVisible - Determines stage visibility in `PetscLogView()`
866 
867   Not Collective
868 
869   Input Parameters:
870 + stage     - The stage
871 - isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
872 
873   Level: intermediate
874 
875   Developer Notes:
876   What does visible mean, needs to be documented.
877 
878 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`
879 @*/
880 PetscErrorCode PetscLogStageSetVisible(PetscLogStage stage, PetscBool isVisible)
881 {
882   PetscStageLog stageLog;
883 
884   PetscFunctionBegin;
885   PetscCall(PetscLogGetStageLog(&stageLog));
886   PetscCall(PetscStageLogSetVisible(stageLog, stage, isVisible));
887   PetscFunctionReturn(PETSC_SUCCESS);
888 }
889 
890 /*@
891   PetscLogStageGetVisible - Returns stage visibility in `PetscLogView()`
892 
893   Not Collective
894 
895   Input Parameter:
896 . stage - The stage
897 
898   Output Parameter:
899 . isVisible - The visibility flag, `PETSC_TRUE` to print, else `PETSC_FALSE` (defaults to `PETSC_TRUE`)
900 
901   Level: intermediate
902 
903 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscLogView()`
904 @*/
905 PetscErrorCode PetscLogStageGetVisible(PetscLogStage stage, PetscBool *isVisible)
906 {
907   PetscStageLog stageLog;
908 
909   PetscFunctionBegin;
910   PetscCall(PetscLogGetStageLog(&stageLog));
911   PetscCall(PetscStageLogGetVisible(stageLog, stage, isVisible));
912   PetscFunctionReturn(PETSC_SUCCESS);
913 }
914 
915 /*@C
916   PetscLogStageGetId - Returns the stage id when given the stage name.
917 
918   Not Collective
919 
920   Input Parameter:
921 . name - The stage name
922 
923   Output Parameter:
924 . stage - The stage, , or -1 if no stage with that name exists
925 
926   Level: intermediate
927 
928 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
929 @*/
930 PetscErrorCode PetscLogStageGetId(const char name[], PetscLogStage *stage)
931 {
932   PetscStageLog stageLog;
933 
934   PetscFunctionBegin;
935   PetscCall(PetscLogGetStageLog(&stageLog));
936   PetscCall(PetscStageLogGetStage(stageLog, name, stage));
937   PetscFunctionReturn(PETSC_SUCCESS);
938 }
939 
940 /*@C
941   PetscLogStageGetName - Returns the stage name when given the stage id.
942 
943   Not Collective
944 
945   Input Parameter:
946 . stage - The stage
947 
948   Output Parameter:
949 . name - The stage name
950 
951   Level: intermediate
952 
953 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogStagePush()`, `PetscLogStagePop()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
954 @*/
955 PetscErrorCode PetscLogStageGetName(PetscLogStage stage, const char **name)
956 {
957   PetscLogStageInfo stage_info;
958   PetscLogState     state;
959 
960   PetscFunctionBegin;
961   PetscCall(PetscLogGetState(&state));
962   PetscCall(PetscLogStateStageGetInfo(state, stage, &stage_info));
963   *name = stage_info.name;
964   PetscFunctionReturn(PETSC_SUCCESS);
965 }
966 
967 /*------------------------------------------------ Event Functions --------------------------------------------------*/
968 
969 /*@C
970   PetscLogEventRegister - Registers an event name for logging operations
971 
972   Not Collective
973 
974   Input Parameters:
975 + name    - The name associated with the event
976 - classid - The classid associated to the class for this event, obtain either with
977            `PetscClassIdRegister()` or use a predefined one such as `KSP_CLASSID`, `SNES_CLASSID`, the predefined ones
978            are only available in C code
979 
980   Output Parameter:
981 . event - The event id for use with `PetscLogEventBegin()` and `PetscLogEventEnd()`.
982 
983   Example Usage:
984 .vb
985       PetscLogEvent USER_EVENT;
986       PetscClassId classid;
987       PetscLogDouble user_event_flops;
988       PetscClassIdRegister("class name",&classid);
989       PetscLogEventRegister("User event name",classid,&USER_EVENT);
990       PetscLogEventBegin(USER_EVENT,0,0,0,0);
991          [code segment to monitor]
992          PetscLogFlops(user_event_flops);
993       PetscLogEventEnd(USER_EVENT,0,0,0,0);
994 .ve
995 
996   Level: intermediate
997 
998   Notes:
999   PETSc automatically logs library events if the code has been
1000   configured with --with-log (which is the default) and
1001   -log_view or -log_all is specified.  `PetscLogEventRegister()` is
1002   intended for logging user events to supplement this PETSc
1003   information.
1004 
1005   PETSc can gather data for use with the utilities Jumpshot
1006   (part of the MPICH distribution).  If PETSc has been compiled
1007   with flag -DPETSC_HAVE_MPE (MPE is an additional utility within
1008   MPICH), the user can employ another command line option, -log_mpe,
1009   to create a logfile, "mpe.log", which can be visualized
1010   Jumpshot.
1011 
1012   The classid is associated with each event so that classes of events
1013   can be disabled simultaneously, such as all matrix events. The user
1014   can either use an existing classid, such as `MAT_CLASSID`, or create
1015   their own as shown in the example.
1016 
1017   If an existing event with the same name exists, its event handle is
1018   returned instead of creating a new event.
1019 
1020 .seealso: [](ch_profiling), `PetscLogStageRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogFlops()`,
1021           `PetscLogEventActivate()`, `PetscLogEventDeactivate()`, `PetscClassIdRegister()`
1022 @*/
1023 PetscErrorCode PetscLogEventRegister(const char name[], PetscClassId classid, PetscLogEvent *event)
1024 {
1025   PetscStageLog stageLog;
1026   int           stage;
1027 
1028   PetscFunctionBegin;
1029   *event = PETSC_DECIDE;
1030   PetscCall(PetscLogGetStageLog(&stageLog));
1031   PetscCall(PetscEventRegLogGetEvent(stageLog->eventLog, name, event));
1032   if (*event > 0) PetscFunctionReturn(PETSC_SUCCESS);
1033   PetscCall(PetscEventRegLogRegister(stageLog->eventLog, name, classid, event));
1034   for (stage = 0; stage < stageLog->numStages; stage++) {
1035     PetscCall(PetscEventPerfLogEnsureSize(stageLog->stageInfo[stage].eventLog, stageLog->eventLog->numEvents));
1036     PetscCall(PetscClassPerfLogEnsureSize(stageLog->stageInfo[stage].classLog, stageLog->classLog->numClasses));
1037   }
1038   PetscFunctionReturn(PETSC_SUCCESS);
1039 }
1040 
1041 /*@
1042   PetscLogEventSetCollective - Indicates that a particular event is collective.
1043 
1044   Not Collective
1045 
1046   Input Parameters:
1047 + event      - The event id
1048 - collective - Boolean flag indicating whether a particular event is collective
1049 
1050   Level: developer
1051 
1052   Notes:
1053   New events returned from `PetscLogEventRegister()` are collective by default.
1054 
1055   Collective events are handled specially if the -log_sync is used. In that case the logging saves information about
1056   two parts of the event; the time for all the MPI ranks to synchronize and then the time for the actual computation/communication
1057   to be performed. This option is useful to debug imbalance within the computations or communications
1058 
1059 .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogEventRegister()`
1060 @*/
1061 PetscErrorCode PetscLogEventSetCollective(PetscLogEvent event, PetscBool collective)
1062 {
1063   PetscStageLog    stageLog;
1064   PetscEventRegLog eventRegLog;
1065 
1066   PetscFunctionBegin;
1067   PetscCall(PetscLogGetStageLog(&stageLog));
1068   PetscCall(PetscStageLogGetEventRegLog(stageLog, &eventRegLog));
1069   PetscCheck(event >= 0 && event <= eventRegLog->numEvents, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid event id");
1070   eventRegLog->eventInfo[event].collective = collective;
1071   PetscFunctionReturn(PETSC_SUCCESS);
1072 }
1073 
1074 /*@
1075   PetscLogEventIncludeClass - Activates event logging for a PETSc object class in every stage.
1076 
1077   Not Collective
1078 
1079   Input Parameter:
1080 . classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1081 
1082   Level: developer
1083 
1084 .seealso: [](ch_profiling), `PetscLogEventActivateClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1085 @*/
1086 PetscErrorCode PetscLogEventIncludeClass(PetscClassId classid)
1087 {
1088   PetscStageLog stageLog;
1089   int           stage;
1090 
1091   PetscFunctionBegin;
1092   PetscCall(PetscLogGetStageLog(&stageLog));
1093   for (stage = 0; stage < stageLog->numStages; stage++) PetscCall(PetscEventPerfLogActivateClass(stageLog->stageInfo[stage].eventLog, stageLog->eventLog, classid));
1094   PetscFunctionReturn(PETSC_SUCCESS);
1095 }
1096 
1097 /*@
1098   PetscLogEventExcludeClass - Deactivates event logging for a PETSc object class in every stage.
1099 
1100   Not Collective
1101 
1102   Input Parameter:
1103 . classid - The object class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1104 
1105   Level: developer
1106 
1107   Note:
1108   If a class is excluded then events associated with that class are not logged.
1109 
1110 .seealso: [](ch_profiling), `PetscLogEventDeactivateClass()`, `PetscLogEventActivateClass()`, `PetscLogEventDeactivate()`, `PetscLogEventActivate()`
1111 @*/
1112 PetscErrorCode PetscLogEventExcludeClass(PetscClassId classid)
1113 {
1114   PetscStageLog stageLog;
1115   int           stage;
1116 
1117   PetscFunctionBegin;
1118   PetscCall(PetscLogGetStageLog(&stageLog));
1119   for (stage = 0; stage < stageLog->numStages; stage++) PetscCall(PetscEventPerfLogDeactivateClass(stageLog->stageInfo[stage].eventLog, stageLog->eventLog, classid));
1120   PetscFunctionReturn(PETSC_SUCCESS);
1121 }
1122 
1123 /*@
1124   PetscLogEventActivate - Indicates that a particular event should be logged.
1125 
1126   Not Collective
1127 
1128   Input Parameter:
1129 . event - The event id
1130 
1131   Example Usage:
1132 .vb
1133       PetscLogEventDeactivate(VEC_SetValues);
1134         [code where you do not want to log VecSetValues()]
1135       PetscLogEventActivate(VEC_SetValues);
1136         [code where you do want to log VecSetValues()]
1137 .ve
1138 
1139   Level: advanced
1140 
1141   Note:
1142   The event may be either a pre-defined PETSc event (found in include/petsclog.h)
1143   or an event number obtained with `PetscLogEventRegister()`.
1144 
1145 .seealso: [](ch_profiling), `PlogEventDeactivate()`, `PlogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1146 @*/
1147 PetscErrorCode PetscLogEventActivate(PetscLogEvent event)
1148 {
1149   PetscStageLog stageLog;
1150   int           stage;
1151 
1152   PetscFunctionBegin;
1153   PetscCall(PetscLogGetStageLog(&stageLog));
1154   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
1155   PetscCall(PetscEventPerfLogActivate(stageLog->stageInfo[stage].eventLog, event));
1156   PetscFunctionReturn(PETSC_SUCCESS);
1157 }
1158 
1159 /*@
1160   PetscLogEventDeactivate - Indicates that a particular event should not be logged.
1161 
1162   Not Collective
1163 
1164   Input Parameter:
1165 . event - The event id
1166 
1167   Example Usage:
1168 .vb
1169       PetscLogEventDeactivate(VEC_SetValues);
1170         [code where you do not want to log VecSetValues()]
1171       PetscLogEventActivate(VEC_SetValues);
1172         [code where you do want to log VecSetValues()]
1173 .ve
1174 
1175   Level: advanced
1176 
1177   Note:
1178   The event may be either a pre-defined PETSc event (found in
1179   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).
1180 
1181 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`
1182 @*/
1183 PetscErrorCode PetscLogEventDeactivate(PetscLogEvent event)
1184 {
1185   PetscStageLog stageLog;
1186   int           stage;
1187 
1188   PetscFunctionBegin;
1189   PetscCall(PetscLogGetStageLog(&stageLog));
1190   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
1191   PetscCall(PetscEventPerfLogDeactivate(stageLog->stageInfo[stage].eventLog, event));
1192   PetscFunctionReturn(PETSC_SUCCESS);
1193 }
1194 
1195 /*@
1196   PetscLogEventDeactivatePush - Indicates that a particular event should not be logged until `PetscLogEventDeactivatePop()` is called
1197 
1198   Not Collective
1199 
1200   Input Parameter:
1201 . event - The event id
1202 
1203   Example Usage:
1204 .vb
1205       PetscLogEventDeactivatePush(VEC_SetValues);
1206         [code where you do not want to log VecSetValues()]
1207       PetscLogEventDeactivatePop(VEC_SetValues);
1208         [code where you do want to log VecSetValues()]
1209 .ve
1210 
1211   Level: advanced
1212 
1213   Note:
1214   The event may be either a pre-defined PETSc event (found in
1215   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).
1216 
1217 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePop()`, `PetscLogEventDeactivate()`
1218 @*/
1219 PetscErrorCode PetscLogEventDeactivatePush(PetscLogEvent event)
1220 {
1221   PetscStageLog stageLog;
1222   int           stage;
1223 
1224   PetscFunctionBegin;
1225   PetscCall(PetscLogGetStageLog(&stageLog));
1226   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
1227   PetscCall(PetscEventPerfLogDeactivatePush(stageLog->stageInfo[stage].eventLog, event));
1228   PetscFunctionReturn(PETSC_SUCCESS);
1229 }
1230 
1231 /*@
1232   PetscLogEventDeactivatePop - Indicates that a particular event should again be logged after the logging was turned off with `PetscLogEventDeactivatePush()`
1233 
1234   Not Collective
1235 
1236   Input Parameter:
1237 . event - The event id
1238 
1239   Example Usage:
1240 .vb
1241       PetscLogEventDeactivatePush(VEC_SetValues);
1242         [code where you do not want to log VecSetValues()]
1243       PetscLogEventDeactivatePop(VEC_SetValues);
1244         [code where you do want to log VecSetValues()]
1245 .ve
1246 
1247   Level: advanced
1248 
1249   Note:
1250   The event may be either a pre-defined PETSc event (found in
1251   include/petsclog.h) or an event number obtained with `PetscLogEventRegister()`).
1252 
1253 .seealso: [](ch_profiling), `PetscLogEventActivate()`, `PetscLogEventDeactivatePush()`
1254 @*/
1255 PetscErrorCode PetscLogEventDeactivatePop(PetscLogEvent event)
1256 {
1257   PetscStageLog stageLog;
1258   int           stage;
1259 
1260   PetscFunctionBegin;
1261   PetscCall(PetscLogGetStageLog(&stageLog));
1262   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
1263   PetscCall(PetscEventPerfLogDeactivatePop(stageLog->stageInfo[stage].eventLog, event));
1264   PetscFunctionReturn(PETSC_SUCCESS);
1265 }
1266 
1267 /*@
1268   PetscLogEventSetActiveAll - Turns on logging of all events
1269 
1270   Not Collective
1271 
1272   Input Parameters:
1273 + event    - The event id
1274 - isActive - The activity flag determining whether the event is logged
1275 
1276   Level: advanced
1277 
1278 .seealso: [](ch_profiling), `PlogEventActivate()`, `PlogEventDeactivate()`
1279 @*/
1280 PetscErrorCode PetscLogEventSetActiveAll(PetscLogEvent event, PetscBool isActive)
1281 {
1282   PetscStageLog stageLog;
1283   int           stage;
1284 
1285   PetscFunctionBegin;
1286   PetscCall(PetscLogGetStageLog(&stageLog));
1287   for (stage = 0; stage < stageLog->numStages; stage++) {
1288     if (isActive) {
1289       PetscCall(PetscEventPerfLogActivate(stageLog->stageInfo[stage].eventLog, event));
1290     } else {
1291       PetscCall(PetscEventPerfLogDeactivate(stageLog->stageInfo[stage].eventLog, event));
1292     }
1293   }
1294   PetscFunctionReturn(PETSC_SUCCESS);
1295 }
1296 
1297 /*@
1298   PetscLogEventActivateClass - Activates event logging for a PETSc object class for the current stage
1299 
1300   Not Collective
1301 
1302   Input Parameter:
1303 . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1304 
1305   Level: developer
1306 
1307 .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventDeactivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1308 @*/
1309 PetscErrorCode PetscLogEventActivateClass(PetscClassId classid)
1310 {
1311   PetscStageLog stageLog;
1312   int           stage;
1313 
1314   PetscFunctionBegin;
1315   PetscCall(PetscLogGetStageLog(&stageLog));
1316   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
1317   PetscCall(PetscEventPerfLogActivateClass(stageLog->stageInfo[stage].eventLog, stageLog->eventLog, classid));
1318   PetscFunctionReturn(PETSC_SUCCESS);
1319 }
1320 
1321 /*@
1322   PetscLogEventDeactivateClass - Deactivates event logging for a PETSc object class for the current stage
1323 
1324   Not Collective
1325 
1326   Input Parameter:
1327 . classid - The event class, for example `MAT_CLASSID`, `SNES_CLASSID`, etc.
1328 
1329   Level: developer
1330 
1331 .seealso: [](ch_profiling), `PetscLogEventIncludeClass()`, `PetscLogEventExcludeClass()`, `PetscLogEventActivateClass()`, `PetscLogEventActivate()`, `PetscLogEventDeactivate()`
1332 @*/
1333 PetscErrorCode PetscLogEventDeactivateClass(PetscClassId classid)
1334 {
1335   PetscStageLog stageLog;
1336   int           stage;
1337 
1338   PetscFunctionBegin;
1339   PetscCall(PetscLogGetStageLog(&stageLog));
1340   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
1341   PetscCall(PetscEventPerfLogDeactivateClass(stageLog->stageInfo[stage].eventLog, stageLog->eventLog, classid));
1342   PetscFunctionReturn(PETSC_SUCCESS);
1343 }
1344 
1345 /*MC
1346   PetscLogEventSync - Synchronizes the beginning of a user event.
1347 
1348   Synopsis:
1349   #include <petsclog.h>
1350   PetscErrorCode PetscLogEventSync(int e, MPI_Comm comm)
1351 
1352   Collective
1353 
1354   Input Parameters:
1355 + e    - integer associated with the event obtained from PetscLogEventRegister()
1356 - comm - an MPI communicator
1357 
1358   Example Usage:
1359 .vb
1360   PetscLogEvent USER_EVENT;
1361 
1362   PetscLogEventRegister("User event", 0, &USER_EVENT);
1363   PetscLogEventSync(USER_EVENT, PETSC_COMM_WORLD);
1364   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1365   [code segment to monitor]
1366   PetscLogEventEnd(USER_EVENT, 0, 0, 0 , 0);
1367 .ve
1368 
1369   Level: developer
1370 
1371   Note:
1372   This routine should be called only if there is not a `PetscObject` available to pass to
1373   `PetscLogEventBegin()`.
1374 
1375 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`
1376 M*/
1377 
1378 /*MC
1379   PetscLogEventBegin - Logs the beginning of a user event.
1380 
1381   Synopsis:
1382   #include <petsclog.h>
1383   PetscErrorCode PetscLogEventBegin(int e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
1384 
1385   Not Collective
1386 
1387   Input Parameters:
1388 + e - integer associated with the event obtained from PetscLogEventRegister()
1389 - o1,o2,o3,o4 - objects associated with the event, or 0
1390 
1391   Fortran Synopsis:
1392   void PetscLogEventBegin(int e, PetscErrorCode ierr)
1393 
1394   Example Usage:
1395 .vb
1396   PetscLogEvent USER_EVENT;
1397 
1398   PetscLogDouble user_event_flops;
1399   PetscLogEventRegister("User event",0, &USER_EVENT);
1400   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1401   [code segment to monitor]
1402   PetscLogFlops(user_event_flops);
1403   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
1404 .ve
1405 
1406   Level: intermediate
1407 
1408   Developer Note:
1409   `PetscLogEventBegin()` and `PetscLogEventBegin()` return error codes instead of explicitly
1410   handling the errors that occur in the macro directly because other packages that use this
1411   macros have used them in their own functions or methods that do not return error codes and it
1412   would be disruptive to change the current behavior.
1413 
1414 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventEnd()`, `PetscLogFlops()`
1415 M*/
1416 
1417 /*MC
1418   PetscLogEventEnd - Log the end of a user event.
1419 
1420   Synopsis:
1421   #include <petsclog.h>
1422   PetscErrorCode PetscLogEventEnd(int e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
1423 
1424   Not Collective
1425 
1426   Input Parameters:
1427 + e - integer associated with the event obtained with PetscLogEventRegister()
1428 - o1,o2,o3,o4 - objects associated with the event, or 0
1429 
1430   Fortran Synopsis:
1431   void PetscLogEventEnd(int e, PetscErrorCode ierr)
1432 
1433   Example Usage:
1434 .vb
1435   PetscLogEvent USER_EVENT;
1436 
1437   PetscLogDouble user_event_flops;
1438   PetscLogEventRegister("User event", 0, &USER_EVENT);
1439   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
1440   [code segment to monitor]
1441   PetscLogFlops(user_event_flops);
1442   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
1443 .ve
1444 
1445   Level: intermediate
1446 
1447 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogFlops()`
1448 M*/
1449 
1450 /*@C
1451   PetscLogEventGetId - Returns the event id when given the event name.
1452 
1453   Not Collective
1454 
1455   Input Parameter:
1456 . name - The event name
1457 
1458   Output Parameter:
1459 . event - The event, or -1 if no event with that name exists
1460 
1461   Level: intermediate
1462 
1463 .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1464 @*/
1465 PetscErrorCode PetscLogEventGetId(const char name[], PetscLogEvent *event)
1466 {
1467   PetscStageLog stageLog;
1468 
1469   PetscFunctionBegin;
1470   PetscCall(PetscLogGetStageLog(&stageLog));
1471   PetscCall(PetscEventRegLogGetEvent(stageLog->eventLog, name, event));
1472   PetscFunctionReturn(PETSC_SUCCESS);
1473 }
1474 
1475 /*@C
1476   PetscLogEventGetName - Returns the event name when given the event id.
1477 
1478   Not Collective
1479 
1480   Input Parameter:
1481 . event - The event
1482 
1483   Output Parameter:
1484 . name  - The event name
1485 
1486   Level: intermediate
1487 
1488 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
1489 @*/
1490 PetscErrorCode PetscLogEventGetName(PetscLogEvent event, const char **name)
1491 {
1492   PetscLogEventInfo event_info;
1493   PetscLogState     state;
1494 
1495   PetscFunctionBegin;
1496   PetscCall(PetscLogGetState(&state));
1497   PetscCall(PetscLogStateEventGetInfo(state, event, &event_info));
1498   *name = event_info.name;
1499   PetscFunctionReturn(PETSC_SUCCESS);
1500 }
1501 
1502 /*@
1503   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.
1504 
1505   Not collective
1506 
1507   Level: advanced
1508 
1509   Notes:
1510   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()`).
1511 
1512   Other log handlers (such as the nested handler, `PetscLogNestedBegin()`) will ignore this function.
1513 
1514 .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsResume()`
1515 @*/
1516 PetscErrorCode PetscLogEventsPause(void)
1517 {
1518   PetscLogHandler handler;
1519 
1520   PetscFunctionBegin;
1521   PetscCall(PetscLogTryGetHandler(PETSC_LOG_HANDLER_DEFAULT, &handler));
1522   if (handler) PetscCall(PetscLogHandlerDefaultEventsPause(handler));
1523   PetscFunctionReturn(PETSC_SUCCESS);
1524 }
1525 
1526 /*@
1527   PetscLogEventsResume - Return logging to normal behavior after it was paused with `PetscLogEventsPause()`.
1528 
1529   Not collective
1530 
1531   Level: advanced
1532 
1533 .seealso: [](ch_profiling), `PetscLogEventDeactivatePush()`, `PetscLogEventDeactivatePop()`, `PetscLogEventsPause()`
1534 @*/
1535 PetscErrorCode PetscLogEventsResume(void)
1536 {
1537   PetscLogHandler handler;
1538 
1539   PetscFunctionBegin;
1540   PetscCall(PetscLogTryGetHandler(PETSC_LOG_HANDLER_DEFAULT, &handler));
1541   if (handler) PetscCall(PetscLogHandlerDefaultEventsResume(handler));
1542   PetscFunctionReturn(PETSC_SUCCESS);
1543 }
1544 
1545 PetscErrorCode PetscLogPushCurrentEvent_Internal(PetscLogEvent event)
1546 {
1547   PetscFunctionBegin;
1548   if (!PetscDefined(HAVE_THREADSAFETY)) PetscCall(PetscIntStackPush(current_log_event_stack, event));
1549   PetscFunctionReturn(PETSC_SUCCESS);
1550 }
1551 
1552 PetscErrorCode PetscLogPopCurrentEvent_Internal(void)
1553 {
1554   PetscFunctionBegin;
1555   if (!PetscDefined(HAVE_THREADSAFETY)) PetscCall(PetscIntStackPop(current_log_event_stack, NULL));
1556   PetscFunctionReturn(PETSC_SUCCESS);
1557 }
1558 
1559 PetscErrorCode PetscLogGetCurrentEvent_Internal(PetscLogEvent *event)
1560 {
1561   PetscBool empty;
1562 
1563   PetscFunctionBegin;
1564   PetscAssertPointer(event, 1);
1565   *event = PETSC_DECIDE;
1566   PetscCall(PetscIntStackEmpty(current_log_event_stack, &empty));
1567   if (!empty) PetscCall(PetscIntStackTop(current_log_event_stack, event));
1568   PetscFunctionReturn(PETSC_SUCCESS);
1569 }
1570 
1571 PetscErrorCode PetscLogEventPause_Internal(PetscLogEvent event)
1572 {
1573   PetscFunctionBegin;
1574   if (event != PETSC_DECIDE) PetscCall(PetscLogEventEnd(event, NULL, NULL, NULL, NULL));
1575   PetscFunctionReturn(PETSC_SUCCESS);
1576 }
1577 
1578 PetscErrorCode PetscLogEventResume_Internal(PetscLogEvent event)
1579 {
1580   PetscStageLog     stageLog;
1581   PetscEventPerfLog eventLog;
1582   int               stage;
1583 
1584   PetscFunctionBegin;
1585   if (event == PETSC_DECIDE) PetscFunctionReturn(PETSC_SUCCESS);
1586   PetscCall(PetscLogEventBegin(event, NULL, NULL, NULL, NULL));
1587   PetscCall(PetscLogGetStageLog(&stageLog));
1588   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
1589   PetscCall(PetscStageLogGetEventPerfLog(stageLog, stage, &eventLog));
1590   eventLog->eventInfo[event].count--;
1591   PetscFunctionReturn(PETSC_SUCCESS);
1592 }
1593 
1594 /*------------------------------------------------ Class Functions --------------------------------------------------*/
1595 
1596 /*MC
1597    PetscLogObjectCreate - Log the creation of a `PetscObject`
1598 
1599    Synopsis:
1600    #include <petsclog.h>
1601    PetscErrorCode PetscLogObjectCreate(PetscObject h)
1602 
1603    Not Collective
1604 
1605    Input Parameters:
1606 .  h - A `PetscObject`
1607 
1608    Level: developer
1609 
1610    Developer Note:
1611      Called internally by PETSc when creating objects: users do not need to call this directly.
1612 
1613 .seealso: [](ch_profiling), `PetscLogObjectDestroy()`
1614 M*/
1615 
1616 /*MC
1617    PetscLogObjectDestroy - Logs the destruction of a `PetscObject`
1618 
1619    Synopsis:
1620    #include <petsclog.h>
1621    PetscErrorCode PetscLogObjectDestroy(PetscObject h)
1622 
1623    Not Collective
1624 
1625    Input Parameters:
1626 .  h - A `PetscObject`
1627 
1628    Level: developer
1629 
1630    Developer Note:
1631      Called internally by PETSc when destroying objects: users do not need to call this directly.
1632 
1633 .seealso: [](ch_profiling), `PetscLogObjectCreate()`
1634 M*/
1635 
1636 /*@C
1637   PetscLogClassGetClassId - Returns the `PetscClassId` when given the class name.
1638 
1639   Not Collective
1640 
1641   Input Parameter:
1642 . name - The class name
1643 
1644   Output Parameter:
1645 . classid - The `PetscClassId` id, or -1 if no class with that name exists
1646 
1647   Level: intermediate
1648 
1649 .seealso: [](ch_profiling), `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscLogStageGetId()`
1650 @*/
1651 PetscErrorCode PetscLogClassGetClassId(const char name[], PetscClassId *classid)
1652 {
1653   PetscLogClass     log_class;
1654   PetscLogClassInfo class_info;
1655   PetscLogState     state;
1656 
1657   PetscFunctionBegin;
1658   PetscCall(PetscLogGetState(&state));
1659   PetscCall(PetscLogStateGetClassFromName(state, name, &log_class));
1660   if (log_class < 0) {
1661     *classid = -1;
1662     PetscFunctionReturn(PETSC_SUCCESS);
1663   }
1664   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
1665   *classid = class_info.classid;
1666   PetscFunctionReturn(PETSC_SUCCESS);
1667 }
1668 
1669 /*@C
1670   PetscLogClassIdGetName - Returns a `PetscClassId`'s name.
1671 
1672   Not Collective
1673 
1674   Input Parameter:
1675 . classid - A `PetscClassId`
1676 
1677   Output Parameter:
1678 . name - The class name
1679 
1680   Level: intermediate
1681 
1682 .seealso: [](ch_profiling), `PetscLogClassRegister()`, `PetscLogClassBegin()`, `PetscLogClassEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`, `PetscPreLoadClass()`
1683 @*/
1684 PetscErrorCode PetscLogClassIdGetName(PetscClassId classid, const char **name)
1685 {
1686   PetscLogClass     log_class;
1687   PetscLogClassInfo class_info;
1688   PetscLogState     state;
1689 
1690   PetscFunctionBegin;
1691   PetscCall(PetscLogGetState(&state));
1692   PetscCall(PetscLogStateGetClassFromClassId(state, classid, &log_class));
1693   PetscCall(PetscLogStateClassGetInfo(state, log_class, &class_info));
1694   *name = class_info.name;
1695   PetscFunctionReturn(PETSC_SUCCESS);
1696 }
1697 
1698 /*------------------------------------------------ Output Functions -------------------------------------------------*/
1699 /*@C
1700   PetscLogDump - Dumps logs of objects to a file. This file is intended to
1701   be read by bin/petscview. This program no longer exists.
1702 
1703   Collective on `PETSC_COMM_WORLD`
1704 
1705   Input Parameter:
1706 . sname - an optional file name
1707 
1708   Example Usage:
1709 .vb
1710   PetscInitialize(...);
1711   PetscLogDefaultBegin(); or PetscLogAllBegin();
1712   ... code ...
1713   PetscLogDump(filename);
1714   PetscFinalize();
1715 .ve
1716 
1717   Level: advanced
1718 
1719   Note:
1720   The default file name is Log.<rank> where <rank> is the MPI process rank. If no name is specified,
1721   this file will be used.
1722 
1723 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogAllBegin()`, `PetscLogView()`
1724 @*/
1725 PetscErrorCode PetscLogDump(const char sname[])
1726 {
1727   PetscStageLog       stageLog;
1728   PetscEventPerfInfo *eventInfo;
1729   FILE               *fd;
1730   char                file[PETSC_MAX_PATH_LEN], fname[PETSC_MAX_PATH_LEN];
1731   PetscLogDouble      flops, _TotalTime;
1732   PetscMPIInt         rank;
1733   int                 action, object, curStage;
1734   PetscLogEvent       event;
1735 
1736   PetscFunctionBegin;
1737   /* Calculate the total elapsed time */
1738   PetscCall(PetscTime(&_TotalTime));
1739   _TotalTime -= petsc_BaseTime;
1740   /* Open log file */
1741   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1742   PetscCall(PetscSNPrintf(file, PETSC_STATIC_ARRAY_LENGTH(file), "%s.%d", sname && sname[0] ? sname : "Log", rank));
1743   PetscCall(PetscFixFilename(file, fname));
1744   PetscCall(PetscFOpen(PETSC_COMM_WORLD, fname, "w", &fd));
1745   PetscCheck(!(rank == 0) || !(!fd), PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open file: %s", fname);
1746   /* Output totals */
1747   PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "Total Flop %14e %16.8e\n", petsc_TotalFlops, _TotalTime));
1748   PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "Clock Resolution %g\n", 0.0));
1749   /* Output actions */
1750   if (petsc_logActions) {
1751     PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "Actions accomplished %d\n", petsc_numActions));
1752     for (action = 0; action < petsc_numActions; action++) {
1753       PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "%g %d %d %d %d %d %d %g %g %g\n", petsc_actions[action].time, petsc_actions[action].action, (int)petsc_actions[action].event, (int)petsc_actions[action].classid, petsc_actions[action].id1,
1754                              petsc_actions[action].id2, petsc_actions[action].id3, petsc_actions[action].flops, petsc_actions[action].mem, petsc_actions[action].maxmem));
1755     }
1756   }
1757   /* Output objects */
1758   if (petsc_logObjects) {
1759     PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "Objects created %d destroyed %d\n", petsc_numObjects, petsc_numObjectsDestroyed));
1760     for (object = 0; object < petsc_numObjects; object++) {
1761       PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "Parent ID: %d Memory: %d\n", petsc_objects[object].parent, (int)petsc_objects[object].mem));
1762       if (!petsc_objects[object].name[0]) {
1763         PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "No Name\n"));
1764       } else {
1765         PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "Name: %s\n", petsc_objects[object].name));
1766       }
1767       if (petsc_objects[object].info[0] != 0) {
1768         PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "No Info\n"));
1769       } else {
1770         PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "Info: %s\n", petsc_objects[object].info));
1771       }
1772     }
1773   }
1774   /* Output events */
1775   PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "Event log:\n"));
1776   PetscCall(PetscLogGetStageLog(&stageLog));
1777   PetscCall(PetscIntStackTop(stageLog->stack, &curStage));
1778   eventInfo = stageLog->stageInfo[curStage].eventLog->eventInfo;
1779   for (event = 0; event < stageLog->stageInfo[curStage].eventLog->numEvents; event++) {
1780     if (eventInfo[event].time != 0.0) flops = eventInfo[event].flops / eventInfo[event].time;
1781     else flops = 0.0;
1782     PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "%d %16d %16g %16g %16g\n", event, eventInfo[event].count, eventInfo[event].flops, eventInfo[event].time, flops));
1783   }
1784   PetscCall(PetscFClose(PETSC_COMM_WORLD, fd));
1785   PetscFunctionReturn(PETSC_SUCCESS);
1786 }
1787 
1788 /*
1789   PetscLogView_Detailed - Each process prints the times for its own events
1790 
1791 */
1792 static PetscErrorCode PetscLogView_Detailed(PetscViewer viewer)
1793 {
1794   PetscStageLog       stageLog;
1795   PetscEventPerfInfo *eventInfo = NULL, *stageInfo = NULL;
1796   PetscLogDouble      locTotalTime, numRed, maxMem;
1797   int                 numStages, numEvents, stage, event;
1798   MPI_Comm            comm = PetscObjectComm((PetscObject)viewer);
1799   PetscMPIInt         rank, size;
1800 
1801   PetscFunctionBegin;
1802   PetscCallMPI(MPI_Comm_size(comm, &size));
1803   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1804   /* Must preserve reduction count before we go on */
1805   numRed = petsc_allreduce_ct + petsc_gather_ct + petsc_scatter_ct;
1806   /* Get the total elapsed time */
1807   PetscCall(PetscTime(&locTotalTime));
1808   locTotalTime -= petsc_BaseTime;
1809   PetscCall(PetscViewerASCIIPrintf(viewer, "size = %d\n", size));
1810   PetscCall(PetscViewerASCIIPrintf(viewer, "LocalTimes = {}\n"));
1811   PetscCall(PetscViewerASCIIPrintf(viewer, "LocalMessages = {}\n"));
1812   PetscCall(PetscViewerASCIIPrintf(viewer, "LocalMessageLens = {}\n"));
1813   PetscCall(PetscViewerASCIIPrintf(viewer, "LocalReductions = {}\n"));
1814   PetscCall(PetscViewerASCIIPrintf(viewer, "LocalFlop = {}\n"));
1815   PetscCall(PetscViewerASCIIPrintf(viewer, "LocalObjects = {}\n"));
1816   PetscCall(PetscViewerASCIIPrintf(viewer, "LocalMemory = {}\n"));
1817   PetscCall(PetscLogGetStageLog(&stageLog));
1818   PetscCallMPI(MPI_Allreduce(&stageLog->numStages, &numStages, 1, MPI_INT, MPI_MAX, comm));
1819   PetscCall(PetscViewerASCIIPrintf(viewer, "Stages = {}\n"));
1820   for (stage = 0; stage < numStages; stage++) {
1821     PetscCall(PetscViewerASCIIPrintf(viewer, "Stages[\"%s\"] = {}\n", stageLog->stageInfo[stage].name));
1822     PetscCall(PetscViewerASCIIPrintf(viewer, "Stages[\"%s\"][\"summary\"] = {}\n", stageLog->stageInfo[stage].name));
1823     PetscCallMPI(MPI_Allreduce(&stageLog->stageInfo[stage].eventLog->numEvents, &numEvents, 1, MPI_INT, MPI_MAX, comm));
1824     for (event = 0; event < numEvents; event++) PetscCall(PetscViewerASCIIPrintf(viewer, "Stages[\"%s\"][\"%s\"] = {}\n", stageLog->stageInfo[stage].name, stageLog->eventLog->eventInfo[event].name));
1825   }
1826   PetscCall(PetscMallocGetMaximumUsage(&maxMem));
1827   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1828   PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "LocalTimes[%d] = %g\n", rank, locTotalTime));
1829   PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "LocalMessages[%d] = %g\n", rank, (petsc_irecv_ct + petsc_isend_ct + petsc_recv_ct + petsc_send_ct)));
1830   PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "LocalMessageLens[%d] = %g\n", rank, (petsc_irecv_len + petsc_isend_len + petsc_recv_len + petsc_send_len)));
1831   PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "LocalReductions[%d] = %g\n", rank, numRed));
1832   PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "LocalFlop[%d] = %g\n", rank, petsc_TotalFlops));
1833   PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "LocalObjects[%d] = %d\n", rank, petsc_numObjects));
1834   PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "LocalMemory[%d] = %g\n", rank, maxMem));
1835   PetscCall(PetscViewerFlush(viewer));
1836   for (stage = 0; stage < numStages; stage++) {
1837     stageInfo = &stageLog->stageInfo[stage].perfInfo;
1838     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Stages[\"%s\"][\"summary\"][%d] = {\"time\" : %g, \"numMessages\" : %g, \"messageLength\" : %g, \"numReductions\" : %g, \"flop\" : %g}\n", stageLog->stageInfo[stage].name, rank, stageInfo->time,
1839                                                  stageInfo->numMessages, stageInfo->messageLength, stageInfo->numReductions, stageInfo->flops));
1840     PetscCallMPI(MPI_Allreduce(&stageLog->stageInfo[stage].eventLog->numEvents, &numEvents, 1, MPI_INT, MPI_MAX, comm));
1841     for (event = 0; event < numEvents; event++) {
1842       eventInfo = &stageLog->stageInfo[stage].eventLog->eventInfo[event];
1843       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Stages[\"%s\"][\"%s\"][%d] = {\"count\" : %d, \"time\" : %g, \"syncTime\" : %g, \"numMessages\" : %g, \"messageLength\" : %g, \"numReductions\" : %g, \"flop\" : %g",
1844                                                    stageLog->stageInfo[stage].name, stageLog->eventLog->eventInfo[event].name, rank, eventInfo->count, eventInfo->time, eventInfo->syncTime, eventInfo->numMessages, eventInfo->messageLength, eventInfo->numReductions,
1845                                                    eventInfo->flops));
1846       if (eventInfo->dof[0] >= 0.) {
1847         PetscInt d, e;
1848 
1849         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ", \"dof\" : ["));
1850         for (d = 0; d < 8; ++d) {
1851           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ", "));
1852           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", eventInfo->dof[d]));
1853         }
1854         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "]"));
1855         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ", \"error\" : ["));
1856         for (e = 0; e < 8; ++e) {
1857           if (e > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ", "));
1858           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", eventInfo->errors[e]));
1859         }
1860         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "]"));
1861       }
1862       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "}\n"));
1863     }
1864   }
1865   PetscCall(PetscViewerFlush(viewer));
1866   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
1867   PetscFunctionReturn(PETSC_SUCCESS);
1868 }
1869 
1870 /*
1871   PetscLogView_CSV - Each process prints the times for its own events in Comma-Separated Value Format
1872 */
1873 static PetscErrorCode PetscLogView_CSV(PetscViewer viewer)
1874 {
1875   PetscStageLog       stageLog;
1876   PetscEventPerfInfo *eventInfo = NULL;
1877   PetscLogDouble      locTotalTime, maxMem;
1878   int                 numStages, numEvents, stage, event;
1879   MPI_Comm            comm = PetscObjectComm((PetscObject)viewer);
1880   PetscMPIInt         rank, size;
1881 
1882   PetscFunctionBegin;
1883   PetscCallMPI(MPI_Comm_size(comm, &size));
1884   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1885   /* Must preserve reduction count before we go on */
1886   /* Get the total elapsed time */
1887   PetscCall(PetscTime(&locTotalTime));
1888   locTotalTime -= petsc_BaseTime;
1889   PetscCall(PetscLogGetStageLog(&stageLog));
1890   PetscCallMPI(MPI_Allreduce(&stageLog->numStages, &numStages, 1, MPI_INT, MPI_MAX, comm));
1891   PetscCall(PetscMallocGetMaximumUsage(&maxMem));
1892   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1893   PetscCall(PetscViewerASCIIPrintf(viewer, "Stage Name,Event Name,Rank,Count,Time,Num Messages,Message Length,Num Reductions,FLOP,dof0,dof1,dof2,dof3,dof4,dof5,dof6,dof7,e0,e1,e2,e3,e4,e5,e6,e7,%d\n", size));
1894   PetscCall(PetscViewerFlush(viewer));
1895   for (stage = 0; stage < numStages; stage++) {
1896     PetscEventPerfInfo *stageInfo = &stageLog->stageInfo[stage].perfInfo;
1897 
1898     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%s,summary,%d,1,%g,%g,%g,%g,%g\n", stageLog->stageInfo[stage].name, rank, stageInfo->time, stageInfo->numMessages, stageInfo->messageLength, stageInfo->numReductions, stageInfo->flops));
1899     PetscCallMPI(MPI_Allreduce(&stageLog->stageInfo[stage].eventLog->numEvents, &numEvents, 1, MPI_INT, MPI_MAX, comm));
1900     for (event = 0; event < numEvents; event++) {
1901       eventInfo = &stageLog->stageInfo[stage].eventLog->eventInfo[event];
1902       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%s,%s,%d,%d,%g,%g,%g,%g,%g", stageLog->stageInfo[stage].name, stageLog->eventLog->eventInfo[event].name, rank, eventInfo->count, eventInfo->time, eventInfo->numMessages, eventInfo->messageLength,
1903                                                    eventInfo->numReductions, eventInfo->flops));
1904       if (eventInfo->dof[0] >= 0.) {
1905         PetscInt d, e;
1906 
1907         for (d = 0; d < 8; ++d) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",%g", eventInfo->dof[d]));
1908         for (e = 0; e < 8; ++e) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",%g", eventInfo->errors[e]));
1909       }
1910       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
1911     }
1912   }
1913   PetscCall(PetscViewerFlush(viewer));
1914   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
1915   PetscFunctionReturn(PETSC_SUCCESS);
1916 }
1917 
1918 static PetscErrorCode PetscLogViewWarnSync(MPI_Comm comm, FILE *fd)
1919 {
1920   PetscFunctionBegin;
1921   if (!PetscLogSyncOn) PetscFunctionReturn(PETSC_SUCCESS);
1922   PetscCall(PetscFPrintf(comm, fd, "\n\n"));
1923   PetscCall(PetscFPrintf(comm, fd, "      ##########################################################\n"));
1924   PetscCall(PetscFPrintf(comm, fd, "      #                                                        #\n"));
1925   PetscCall(PetscFPrintf(comm, fd, "      #                       WARNING!!!                       #\n"));
1926   PetscCall(PetscFPrintf(comm, fd, "      #                                                        #\n"));
1927   PetscCall(PetscFPrintf(comm, fd, "      #   This program was run with logging synchronization.   #\n"));
1928   PetscCall(PetscFPrintf(comm, fd, "      #   This option provides more meaningful imbalance       #\n"));
1929   PetscCall(PetscFPrintf(comm, fd, "      #   figures at the expense of slowing things down and    #\n"));
1930   PetscCall(PetscFPrintf(comm, fd, "      #   providing a distorted view of the overall runtime.   #\n"));
1931   PetscCall(PetscFPrintf(comm, fd, "      #                                                        #\n"));
1932   PetscCall(PetscFPrintf(comm, fd, "      ##########################################################\n\n\n"));
1933   PetscFunctionReturn(PETSC_SUCCESS);
1934 }
1935 
1936 static PetscErrorCode PetscLogViewWarnDebugging(MPI_Comm comm, FILE *fd)
1937 {
1938   PetscFunctionBegin;
1939   if (PetscDefined(USE_DEBUG)) {
1940     PetscCall(PetscFPrintf(comm, fd, "\n\n"));
1941     PetscCall(PetscFPrintf(comm, fd, "      ##########################################################\n"));
1942     PetscCall(PetscFPrintf(comm, fd, "      #                                                        #\n"));
1943     PetscCall(PetscFPrintf(comm, fd, "      #                       WARNING!!!                       #\n"));
1944     PetscCall(PetscFPrintf(comm, fd, "      #                                                        #\n"));
1945     PetscCall(PetscFPrintf(comm, fd, "      #   This code was compiled with a debugging option.      #\n"));
1946     PetscCall(PetscFPrintf(comm, fd, "      #   To get timing results run ./configure                #\n"));
1947     PetscCall(PetscFPrintf(comm, fd, "      #   using --with-debugging=no, the performance will      #\n"));
1948     PetscCall(PetscFPrintf(comm, fd, "      #   be generally two or three times faster.              #\n"));
1949     PetscCall(PetscFPrintf(comm, fd, "      #                                                        #\n"));
1950     PetscCall(PetscFPrintf(comm, fd, "      ##########################################################\n\n\n"));
1951   }
1952   PetscFunctionReturn(PETSC_SUCCESS);
1953 }
1954 
1955 static PetscErrorCode PetscLogViewWarnNoGpuAwareMpi(MPI_Comm comm, FILE *fd)
1956 {
1957   #if defined(PETSC_HAVE_DEVICE)
1958   PetscMPIInt size;
1959   PetscBool   deviceInitialized = PETSC_FALSE;
1960 
1961   PetscFunctionBegin;
1962   PetscCallMPI(MPI_Comm_size(comm, &size));
1963   for (int i = PETSC_DEVICE_HOST + 1; i < PETSC_DEVICE_MAX; ++i) {
1964     const PetscDeviceType dtype = PetscDeviceTypeCast(i);
1965     if (PetscDeviceInitialized(dtype)) { /* a non-host device was initialized */
1966       deviceInitialized = PETSC_TRUE;
1967       break;
1968     }
1969   }
1970   /* the last condition says petsc is configured with device but it is a pure CPU run, so don't print misleading warnings */
1971   if (use_gpu_aware_mpi || size == 1 || !deviceInitialized) PetscFunctionReturn(PETSC_SUCCESS);
1972   PetscCall(PetscFPrintf(comm, fd, "\n\n"));
1973   PetscCall(PetscFPrintf(comm, fd, "      ##########################################################\n"));
1974   PetscCall(PetscFPrintf(comm, fd, "      #                                                        #\n"));
1975   PetscCall(PetscFPrintf(comm, fd, "      #                       WARNING!!!                       #\n"));
1976   PetscCall(PetscFPrintf(comm, fd, "      #                                                        #\n"));
1977   PetscCall(PetscFPrintf(comm, fd, "      #   This code was compiled with GPU support and you've   #\n"));
1978   PetscCall(PetscFPrintf(comm, fd, "      #   created PETSc/GPU objects, but you intentionally     #\n"));
1979   PetscCall(PetscFPrintf(comm, fd, "      #   used -use_gpu_aware_mpi 0, requiring PETSc to copy   #\n"));
1980   PetscCall(PetscFPrintf(comm, fd, "      #   additional data between the GPU and CPU. To obtain   #\n"));
1981   PetscCall(PetscFPrintf(comm, fd, "      #   meaningful timing results on multi-rank runs, use    #\n"));
1982   PetscCall(PetscFPrintf(comm, fd, "      #   GPU-aware MPI instead.                               #\n"));
1983   PetscCall(PetscFPrintf(comm, fd, "      #                                                        #\n"));
1984   PetscCall(PetscFPrintf(comm, fd, "      ##########################################################\n\n\n"));
1985   PetscFunctionReturn(PETSC_SUCCESS);
1986   #else
1987   (void)comm;
1988   (void)fd;
1989   return PETSC_SUCCESS;
1990   #endif
1991 }
1992 
1993 static PetscErrorCode PetscLogViewWarnGpuTime(MPI_Comm comm, FILE *fd)
1994 {
1995   #if defined(PETSC_HAVE_DEVICE)
1996 
1997   PetscFunctionBegin;
1998   if (!PetscLogGpuTimeFlag || petsc_gflops == 0) PetscFunctionReturn(PETSC_SUCCESS);
1999   PetscCall(PetscFPrintf(comm, fd, "\n\n"));
2000   PetscCall(PetscFPrintf(comm, fd, "      ##########################################################\n"));
2001   PetscCall(PetscFPrintf(comm, fd, "      #                                                        #\n"));
2002   PetscCall(PetscFPrintf(comm, fd, "      #                       WARNING!!!                       #\n"));
2003   PetscCall(PetscFPrintf(comm, fd, "      #                                                        #\n"));
2004   PetscCall(PetscFPrintf(comm, fd, "      #   This code was run with -log_view_gpu_time            #\n"));
2005   PetscCall(PetscFPrintf(comm, fd, "      #   This provides accurate timing within the GPU kernels #\n"));
2006   PetscCall(PetscFPrintf(comm, fd, "      #   but can slow down the entire computation by a        #\n"));
2007   PetscCall(PetscFPrintf(comm, fd, "      #   measurable amount. For fastest runs we recommend     #\n"));
2008   PetscCall(PetscFPrintf(comm, fd, "      #   not using this option.                               #\n"));
2009   PetscCall(PetscFPrintf(comm, fd, "      #                                                        #\n"));
2010   PetscCall(PetscFPrintf(comm, fd, "      ##########################################################\n\n\n"));
2011   PetscFunctionReturn(PETSC_SUCCESS);
2012   #else
2013   (void)comm;
2014   (void)fd;
2015   return PETSC_SUCCESS;
2016   #endif
2017 }
2018 
2019 static PetscErrorCode PetscLogView_Default(PetscViewer viewer)
2020 {
2021   FILE               *fd;
2022   PetscLogDouble      zero = 0.0;
2023   PetscStageLog       stageLog;
2024   PetscStageInfo     *stageInfo = NULL;
2025   PetscEventPerfInfo *eventInfo = NULL;
2026   PetscClassPerfInfo *classInfo;
2027   char                arch[128], hostname[128], username[128], pname[PETSC_MAX_PATH_LEN], date[128];
2028   const char         *name;
2029   PetscLogDouble      locTotalTime, TotalTime, TotalFlops;
2030   PetscLogDouble      numMessages, messageLength, avgMessLen, numReductions;
2031   PetscLogDouble      stageTime, flops, flopr, mem, mess, messLen, red;
2032   PetscLogDouble      fracTime, fracFlops, fracMessages, fracLength, fracReductions, fracMess, fracMessLen, fracRed;
2033   PetscLogDouble      fracStageTime, fracStageFlops, fracStageMess, fracStageMessLen, fracStageRed;
2034   PetscLogDouble      min, max, tot, ratio, avg, x, y;
2035   PetscLogDouble      minf, maxf, totf, ratf, mint, maxt, tott, ratt, ratC, totm, totml, totr, mal, malmax, emalmax;
2036   #if defined(PETSC_HAVE_DEVICE)
2037   PetscLogEvent  KSP_Solve, SNES_Solve, TS_Step, TAO_Solve; /* These need to be fixed to be some events registered with certain objects */
2038   PetscLogDouble cct, gct, csz, gsz, gmaxt, gflops, gflopr, fracgflops;
2039   #endif
2040   PetscMPIInt   minC, maxC;
2041   PetscMPIInt   size, rank;
2042   PetscBool    *localStageUsed, *stageUsed;
2043   PetscBool    *localStageVisible, *stageVisible;
2044   int           numStages, localNumEvents, numEvents;
2045   int           stage, oclass;
2046   PetscLogEvent event;
2047   char          version[256];
2048   MPI_Comm      comm;
2049   #if defined(PETSC_HAVE_DEVICE)
2050   PetscLogEvent eventid;
2051   PetscInt64    nas = 0x7FF0000000000002;
2052   #endif
2053 
2054   PetscFunctionBegin;
2055   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
2056   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
2057   PetscCall(PetscViewerASCIIGetPointer(viewer, &fd));
2058   PetscCallMPI(MPI_Comm_size(comm, &size));
2059   PetscCallMPI(MPI_Comm_rank(comm, &rank));
2060   /* Get the total elapsed time */
2061   PetscCall(PetscTime(&locTotalTime));
2062   locTotalTime -= petsc_BaseTime;
2063 
2064   PetscCall(PetscFPrintf(comm, fd, "****************************************************************************************************************************************************************\n"));
2065   PetscCall(PetscFPrintf(comm, fd, "***                                WIDEN YOUR WINDOW TO 160 CHARACTERS.  Use 'enscript -r -fCourier9' to print this document                                 ***\n"));
2066   PetscCall(PetscFPrintf(comm, fd, "****************************************************************************************************************************************************************\n"));
2067   PetscCall(PetscFPrintf(comm, fd, "\n------------------------------------------------------------------ PETSc Performance Summary: ------------------------------------------------------------------\n\n"));
2068   PetscCall(PetscLogViewWarnSync(comm, fd));
2069   PetscCall(PetscLogViewWarnDebugging(comm, fd));
2070   PetscCall(PetscLogViewWarnNoGpuAwareMpi(comm, fd));
2071   PetscCall(PetscLogViewWarnGpuTime(comm, fd));
2072   PetscCall(PetscGetArchType(arch, sizeof(arch)));
2073   PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
2074   PetscCall(PetscGetUserName(username, sizeof(username)));
2075   PetscCall(PetscGetProgramName(pname, sizeof(pname)));
2076   PetscCall(PetscGetDate(date, sizeof(date)));
2077   PetscCall(PetscGetVersion(version, sizeof(version)));
2078   if (size == 1) {
2079     PetscCall(PetscFPrintf(comm, fd, "%s on a %s named %s with %d processor, by %s %s\n", pname, arch, hostname, size, username, date));
2080   } else {
2081     PetscCall(PetscFPrintf(comm, fd, "%s on a %s named %s with %d processors, by %s %s\n", pname, arch, hostname, size, username, date));
2082   }
2083   #if defined(PETSC_HAVE_OPENMP)
2084   PetscCall(PetscFPrintf(comm, fd, "Using %" PetscInt_FMT " OpenMP threads\n", PetscNumOMPThreads));
2085   #endif
2086   PetscCall(PetscFPrintf(comm, fd, "Using %s\n", version));
2087 
2088   /* Must preserve reduction count before we go on */
2089   red = petsc_allreduce_ct + petsc_gather_ct + petsc_scatter_ct;
2090 
2091   /* Calculate summary information */
2092   PetscCall(PetscFPrintf(comm, fd, "\n                         Max       Max/Min     Avg       Total\n"));
2093   /*   Time */
2094   PetscCall(MPIU_Allreduce(&locTotalTime, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm));
2095   PetscCall(MPIU_Allreduce(&locTotalTime, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2096   PetscCall(MPIU_Allreduce(&locTotalTime, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2097   avg = tot / ((PetscLogDouble)size);
2098   if (min != 0.0) ratio = max / min;
2099   else ratio = 0.0;
2100   PetscCall(PetscFPrintf(comm, fd, "Time (sec):           %5.3e   %7.3f   %5.3e\n", max, ratio, avg));
2101   TotalTime = tot;
2102   /*   Objects */
2103   avg = (PetscLogDouble)petsc_numObjects;
2104   PetscCall(MPIU_Allreduce(&avg, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm));
2105   PetscCall(MPIU_Allreduce(&avg, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2106   PetscCall(MPIU_Allreduce(&avg, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2107   avg = tot / ((PetscLogDouble)size);
2108   if (min != 0.0) ratio = max / min;
2109   else ratio = 0.0;
2110   PetscCall(PetscFPrintf(comm, fd, "Objects:              %5.3e   %7.3f   %5.3e\n", max, ratio, avg));
2111   /*   Flops */
2112   PetscCall(MPIU_Allreduce(&petsc_TotalFlops, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm));
2113   PetscCall(MPIU_Allreduce(&petsc_TotalFlops, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2114   PetscCall(MPIU_Allreduce(&petsc_TotalFlops, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2115   avg = tot / ((PetscLogDouble)size);
2116   if (min != 0.0) ratio = max / min;
2117   else ratio = 0.0;
2118   PetscCall(PetscFPrintf(comm, fd, "Flops:                %5.3e   %7.3f   %5.3e  %5.3e\n", max, ratio, avg, tot));
2119   TotalFlops = tot;
2120   /*   Flops/sec -- Must talk to Barry here */
2121   if (locTotalTime != 0.0) flops = petsc_TotalFlops / locTotalTime;
2122   else flops = 0.0;
2123   PetscCall(MPIU_Allreduce(&flops, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm));
2124   PetscCall(MPIU_Allreduce(&flops, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2125   PetscCall(MPIU_Allreduce(&flops, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2126   avg = tot / ((PetscLogDouble)size);
2127   if (min != 0.0) ratio = max / min;
2128   else ratio = 0.0;
2129   PetscCall(PetscFPrintf(comm, fd, "Flops/sec:            %5.3e   %7.3f   %5.3e  %5.3e\n", max, ratio, avg, tot));
2130   /*   Memory */
2131   PetscCall(PetscMallocGetMaximumUsage(&mem));
2132   if (mem > 0.0) {
2133     PetscCall(MPIU_Allreduce(&mem, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm));
2134     PetscCall(MPIU_Allreduce(&mem, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2135     PetscCall(MPIU_Allreduce(&mem, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2136     avg = tot / ((PetscLogDouble)size);
2137     if (min != 0.0) ratio = max / min;
2138     else ratio = 0.0;
2139     PetscCall(PetscFPrintf(comm, fd, "Memory (bytes):       %5.3e   %7.3f   %5.3e  %5.3e\n", max, ratio, avg, tot));
2140   }
2141   /*   Messages */
2142   mess = 0.5 * (petsc_irecv_ct + petsc_isend_ct + petsc_recv_ct + petsc_send_ct);
2143   PetscCall(MPIU_Allreduce(&mess, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm));
2144   PetscCall(MPIU_Allreduce(&mess, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2145   PetscCall(MPIU_Allreduce(&mess, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2146   avg = tot / ((PetscLogDouble)size);
2147   if (min != 0.0) ratio = max / min;
2148   else ratio = 0.0;
2149   PetscCall(PetscFPrintf(comm, fd, "MPI Msg Count:        %5.3e   %7.3f   %5.3e  %5.3e\n", max, ratio, avg, tot));
2150   numMessages = tot;
2151   /*   Message Lengths */
2152   mess = 0.5 * (petsc_irecv_len + petsc_isend_len + petsc_recv_len + petsc_send_len);
2153   PetscCall(MPIU_Allreduce(&mess, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm));
2154   PetscCall(MPIU_Allreduce(&mess, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2155   PetscCall(MPIU_Allreduce(&mess, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2156   if (numMessages != 0) avg = tot / numMessages;
2157   else avg = 0.0;
2158   if (min != 0.0) ratio = max / min;
2159   else ratio = 0.0;
2160   PetscCall(PetscFPrintf(comm, fd, "MPI Msg Len (bytes):  %5.3e   %7.3f   %5.3e  %5.3e\n", max, ratio, avg, tot));
2161   messageLength = tot;
2162   /*   Reductions */
2163   PetscCall(MPIU_Allreduce(&red, &min, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm));
2164   PetscCall(MPIU_Allreduce(&red, &max, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2165   PetscCall(MPIU_Allreduce(&red, &tot, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2166   if (min != 0.0) ratio = max / min;
2167   else ratio = 0.0;
2168   PetscCall(PetscFPrintf(comm, fd, "MPI Reductions:       %5.3e   %7.3f\n", max, ratio));
2169   numReductions = red; /* wrong because uses count from process zero */
2170   PetscCall(PetscFPrintf(comm, fd, "\nFlop counting convention: 1 flop = 1 real number operation of type (multiply/divide/add/subtract)\n"));
2171   PetscCall(PetscFPrintf(comm, fd, "                            e.g., VecAXPY() for real vectors of length N --> 2N flops\n"));
2172   PetscCall(PetscFPrintf(comm, fd, "                            and VecAXPY() for complex vectors of length N --> 8N flops\n"));
2173 
2174   /* Get total number of stages --
2175        Currently, a single processor can register more stages than another, but stages must all be registered in order.
2176        We can removed this requirement if necessary by having a global stage numbering and indirection on the stage ID.
2177        This seems best accomplished by assoicating a communicator with each stage.
2178   */
2179   PetscCall(PetscLogGetStageLog(&stageLog));
2180   PetscCallMPI(MPI_Allreduce(&stageLog->numStages, &numStages, 1, MPI_INT, MPI_MAX, comm));
2181   PetscCall(PetscMalloc1(numStages, &localStageUsed));
2182   PetscCall(PetscMalloc1(numStages, &stageUsed));
2183   PetscCall(PetscMalloc1(numStages, &localStageVisible));
2184   PetscCall(PetscMalloc1(numStages, &stageVisible));
2185   if (numStages > 0) {
2186     stageInfo = stageLog->stageInfo;
2187     for (stage = 0; stage < numStages; stage++) {
2188       if (stage < stageLog->numStages) {
2189         localStageUsed[stage]    = stageInfo[stage].used;
2190         localStageVisible[stage] = stageInfo[stage].perfInfo.visible;
2191       } else {
2192         localStageUsed[stage]    = PETSC_FALSE;
2193         localStageVisible[stage] = PETSC_TRUE;
2194       }
2195     }
2196     PetscCall(MPIU_Allreduce(localStageUsed, stageUsed, numStages, MPIU_BOOL, MPI_LOR, comm));
2197     PetscCall(MPIU_Allreduce(localStageVisible, stageVisible, numStages, MPIU_BOOL, MPI_LAND, comm));
2198     for (stage = 0; stage < numStages; stage++) {
2199       if (stageUsed[stage]) {
2200         PetscCall(PetscFPrintf(comm, fd, "\nSummary of Stages:   ----- Time ------  ----- Flop ------  --- Messages ---  -- Message Lengths --  -- Reductions --\n"));
2201         PetscCall(PetscFPrintf(comm, fd, "                        Avg     %%Total     Avg     %%Total    Count   %%Total     Avg         %%Total    Count   %%Total\n"));
2202         break;
2203       }
2204     }
2205     for (stage = 0; stage < numStages; stage++) {
2206       if (!stageUsed[stage]) continue;
2207       /* CANNOT use MPI_Allreduce() since it might fail the line number check */
2208       if (localStageUsed[stage]) {
2209         PetscCall(MPIU_Allreduce(&stageInfo[stage].perfInfo.time, &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2210         PetscCall(MPIU_Allreduce(&stageInfo[stage].perfInfo.flops, &flops, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2211         PetscCall(MPIU_Allreduce(&stageInfo[stage].perfInfo.numMessages, &mess, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2212         PetscCall(MPIU_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2213         PetscCall(MPIU_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2214         name = stageInfo[stage].name;
2215       } else {
2216         PetscCall(MPIU_Allreduce(&zero, &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2217         PetscCall(MPIU_Allreduce(&zero, &flops, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2218         PetscCall(MPIU_Allreduce(&zero, &mess, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2219         PetscCall(MPIU_Allreduce(&zero, &messLen, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2220         PetscCall(MPIU_Allreduce(&zero, &red, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2221         name = "";
2222       }
2223       mess *= 0.5;
2224       messLen *= 0.5;
2225       red /= size;
2226       if (TotalTime != 0.0) fracTime = stageTime / TotalTime;
2227       else fracTime = 0.0;
2228       if (TotalFlops != 0.0) fracFlops = flops / TotalFlops;
2229       else fracFlops = 0.0;
2230       /* Talk to Barry if (stageTime     != 0.0) flops          = (size*flops)/stageTime; else flops          = 0.0; */
2231       if (numMessages != 0.0) fracMessages = mess / numMessages;
2232       else fracMessages = 0.0;
2233       if (mess != 0.0) avgMessLen = messLen / mess;
2234       else avgMessLen = 0.0;
2235       if (messageLength != 0.0) fracLength = messLen / messageLength;
2236       else fracLength = 0.0;
2237       if (numReductions != 0.0) fracReductions = red / numReductions;
2238       else fracReductions = 0.0;
2239       PetscCall(PetscFPrintf(comm, fd, "%2d: %15s: %6.4e %5.1f%%  %6.4e %5.1f%%  %5.3e %5.1f%%  %5.3e      %5.1f%%  %5.3e %5.1f%%\n", stage, name, stageTime / size, 100.0 * fracTime, flops, 100.0 * fracFlops, mess, 100.0 * fracMessages, avgMessLen, 100.0 * fracLength, red, 100.0 * fracReductions));
2240     }
2241   }
2242 
2243   PetscCall(PetscFPrintf(comm, fd, "\n------------------------------------------------------------------------------------------------------------------------\n"));
2244   PetscCall(PetscFPrintf(comm, fd, "See the 'Profiling' chapter of the users' manual for details on interpreting output.\n"));
2245   PetscCall(PetscFPrintf(comm, fd, "Phase summary info:\n"));
2246   PetscCall(PetscFPrintf(comm, fd, "   Count: number of times phase was executed\n"));
2247   PetscCall(PetscFPrintf(comm, fd, "   Time and Flop: Max - maximum over all processors\n"));
2248   PetscCall(PetscFPrintf(comm, fd, "                  Ratio - ratio of maximum to minimum over all processors\n"));
2249   PetscCall(PetscFPrintf(comm, fd, "   Mess: number of messages sent\n"));
2250   PetscCall(PetscFPrintf(comm, fd, "   AvgLen: average message length (bytes)\n"));
2251   PetscCall(PetscFPrintf(comm, fd, "   Reduct: number of global reductions\n"));
2252   PetscCall(PetscFPrintf(comm, fd, "   Global: entire computation\n"));
2253   PetscCall(PetscFPrintf(comm, fd, "   Stage: stages of a computation. Set stages with PetscLogStagePush() and PetscLogStagePop().\n"));
2254   PetscCall(PetscFPrintf(comm, fd, "      %%T - percent time in this phase         %%F - percent flop in this phase\n"));
2255   PetscCall(PetscFPrintf(comm, fd, "      %%M - percent messages in this phase     %%L - percent message lengths in this phase\n"));
2256   PetscCall(PetscFPrintf(comm, fd, "      %%R - percent reductions in this phase\n"));
2257   PetscCall(PetscFPrintf(comm, fd, "   Total Mflop/s: 10e-6 * (sum of flop over all processors)/(max time over all processors)\n"));
2258   if (PetscLogMemory) {
2259     PetscCall(PetscFPrintf(comm, fd, "   Memory usage is summed over all MPI processes, it is given in mega-bytes\n"));
2260     PetscCall(PetscFPrintf(comm, fd, "   Malloc Mbytes: Memory allocated and kept during event (sum over all calls to event). May be negative\n"));
2261     PetscCall(PetscFPrintf(comm, fd, "   EMalloc Mbytes: extra memory allocated during event and then freed (maximum over all calls to events). Never negative\n"));
2262     PetscCall(PetscFPrintf(comm, fd, "   MMalloc Mbytes: Increase in high water mark of allocated memory (sum over all calls to event). Never negative\n"));
2263     PetscCall(PetscFPrintf(comm, fd, "   RMI Mbytes: Increase in resident memory (sum over all calls to event)\n"));
2264   }
2265   #if defined(PETSC_HAVE_DEVICE)
2266   PetscCall(PetscFPrintf(comm, fd, "   GPU Mflop/s: 10e-6 * (sum of flop on GPU over all processors)/(max GPU time over all processors)\n"));
2267   PetscCall(PetscFPrintf(comm, fd, "   CpuToGpu Count: total number of CPU to GPU copies per processor\n"));
2268   PetscCall(PetscFPrintf(comm, fd, "   CpuToGpu Size (Mbytes): 10e-6 * (total size of CPU to GPU copies per processor)\n"));
2269   PetscCall(PetscFPrintf(comm, fd, "   GpuToCpu Count: total number of GPU to CPU copies per processor\n"));
2270   PetscCall(PetscFPrintf(comm, fd, "   GpuToCpu Size (Mbytes): 10e-6 * (total size of GPU to CPU copies per processor)\n"));
2271   PetscCall(PetscFPrintf(comm, fd, "   GPU %%F: percent flops on GPU in this event\n"));
2272   #endif
2273   PetscCall(PetscFPrintf(comm, fd, "------------------------------------------------------------------------------------------------------------------------\n"));
2274 
2275   PetscCall(PetscLogViewWarnDebugging(comm, fd));
2276 
2277   /* Report events */
2278   PetscCall(PetscFPrintf(comm, fd, "Event                Count      Time (sec)     Flop                              --- Global ---  --- Stage ----  Total"));
2279   if (PetscLogMemory) PetscCall(PetscFPrintf(comm, fd, "  Malloc EMalloc MMalloc RMI"));
2280   #if defined(PETSC_HAVE_DEVICE)
2281   PetscCall(PetscFPrintf(comm, fd, "   GPU    - CpuToGpu -   - GpuToCpu - GPU"));
2282   #endif
2283   PetscCall(PetscFPrintf(comm, fd, "\n"));
2284   PetscCall(PetscFPrintf(comm, fd, "                   Max Ratio  Max     Ratio   Max  Ratio  Mess   AvgLen  Reduct  %%T %%F %%M %%L %%R  %%T %%F %%M %%L %%R Mflop/s"));
2285   if (PetscLogMemory) PetscCall(PetscFPrintf(comm, fd, " Mbytes Mbytes Mbytes Mbytes"));
2286   #if defined(PETSC_HAVE_DEVICE)
2287   PetscCall(PetscFPrintf(comm, fd, " Mflop/s Count   Size   Count   Size  %%F"));
2288   #endif
2289   PetscCall(PetscFPrintf(comm, fd, "\n"));
2290   PetscCall(PetscFPrintf(comm, fd, "------------------------------------------------------------------------------------------------------------------------"));
2291   if (PetscLogMemory) PetscCall(PetscFPrintf(comm, fd, "-----------------------------"));
2292   #if defined(PETSC_HAVE_DEVICE)
2293   PetscCall(PetscFPrintf(comm, fd, "---------------------------------------"));
2294   #endif
2295   PetscCall(PetscFPrintf(comm, fd, "\n"));
2296 
2297   #if defined(PETSC_HAVE_DEVICE)
2298   /* this indirect way of accessing these values is needed when PETSc is build with multiple libraries since the symbols are not in libpetscsys */
2299   PetscCall(PetscEventRegLogGetEvent(stageLog->eventLog, "TAOSolve", &TAO_Solve));
2300   PetscCall(PetscEventRegLogGetEvent(stageLog->eventLog, "TSStep", &TS_Step));
2301   PetscCall(PetscEventRegLogGetEvent(stageLog->eventLog, "SNESSolve", &SNES_Solve));
2302   PetscCall(PetscEventRegLogGetEvent(stageLog->eventLog, "KSPSolve", &KSP_Solve));
2303   #endif
2304 
2305   /* Problem: The stage name will not show up unless the stage executed on proc 1 */
2306   for (stage = 0; stage < numStages; stage++) {
2307     if (!stageVisible[stage]) continue;
2308     /* CANNOT use MPI_Allreduce() since it might fail the line number check */
2309     if (localStageUsed[stage]) {
2310       PetscCall(PetscFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name));
2311       PetscCall(MPIU_Allreduce(&stageInfo[stage].perfInfo.time, &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2312       PetscCall(MPIU_Allreduce(&stageInfo[stage].perfInfo.flops, &flops, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2313       PetscCall(MPIU_Allreduce(&stageInfo[stage].perfInfo.numMessages, &mess, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2314       PetscCall(MPIU_Allreduce(&stageInfo[stage].perfInfo.messageLength, &messLen, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2315       PetscCall(MPIU_Allreduce(&stageInfo[stage].perfInfo.numReductions, &red, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2316     } else {
2317       PetscCall(PetscFPrintf(comm, fd, "\n--- Event Stage %d: Unknown\n\n", stage));
2318       PetscCall(MPIU_Allreduce(&zero, &stageTime, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2319       PetscCall(MPIU_Allreduce(&zero, &flops, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2320       PetscCall(MPIU_Allreduce(&zero, &mess, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2321       PetscCall(MPIU_Allreduce(&zero, &messLen, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2322       PetscCall(MPIU_Allreduce(&zero, &red, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2323     }
2324     mess *= 0.5;
2325     messLen *= 0.5;
2326     red /= size;
2327 
2328     /* Get total number of events in this stage --
2329        Currently, a single processor can register more events than another, but events must all be registered in order,
2330        just like stages. We can removed this requirement if necessary by having a global event numbering and indirection
2331        on the event ID. This seems best accomplished by associating a communicator with each stage.
2332 
2333        Problem: If the event did not happen on proc 1, its name will not be available.
2334        Problem: Event visibility is not implemented
2335     */
2336     if (localStageUsed[stage]) {
2337       eventInfo      = stageLog->stageInfo[stage].eventLog->eventInfo;
2338       localNumEvents = stageLog->stageInfo[stage].eventLog->numEvents;
2339     } else localNumEvents = 0;
2340     PetscCallMPI(MPI_Allreduce(&localNumEvents, &numEvents, 1, MPI_INT, MPI_MAX, comm));
2341     for (event = 0; event < numEvents; event++) {
2342       /* CANNOT use MPI_Allreduce() since it might fail the line number check */
2343       if (localStageUsed[stage] && (event < stageLog->stageInfo[stage].eventLog->numEvents) && (eventInfo[event].depth == 0)) {
2344         if ((eventInfo[event].count > 0) && (eventInfo[event].time > 0.0)) flopr = eventInfo[event].flops;
2345         else flopr = 0.0;
2346         PetscCall(MPIU_Allreduce(&flopr, &minf, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm));
2347         PetscCall(MPIU_Allreduce(&flopr, &maxf, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2348         PetscCall(MPIU_Allreduce(&eventInfo[event].flops, &totf, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2349         PetscCall(MPIU_Allreduce(&eventInfo[event].time, &mint, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm));
2350         PetscCall(MPIU_Allreduce(&eventInfo[event].time, &maxt, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2351         PetscCall(MPIU_Allreduce(&eventInfo[event].time, &tott, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2352         PetscCall(MPIU_Allreduce(&eventInfo[event].numMessages, &totm, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2353         PetscCall(MPIU_Allreduce(&eventInfo[event].messageLength, &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2354         PetscCall(MPIU_Allreduce(&eventInfo[event].numReductions, &totr, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2355         PetscCallMPI(MPI_Allreduce(&eventInfo[event].count, &minC, 1, MPI_INT, MPI_MIN, comm));
2356         PetscCallMPI(MPI_Allreduce(&eventInfo[event].count, &maxC, 1, MPI_INT, MPI_MAX, comm));
2357         if (PetscLogMemory) {
2358           PetscCall(MPIU_Allreduce(&eventInfo[event].memIncrease, &mem, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2359           PetscCall(MPIU_Allreduce(&eventInfo[event].mallocSpace, &mal, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2360           PetscCall(MPIU_Allreduce(&eventInfo[event].mallocIncrease, &malmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2361           PetscCall(MPIU_Allreduce(&eventInfo[event].mallocIncreaseEvent, &emalmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2362         }
2363   #if defined(PETSC_HAVE_DEVICE)
2364         PetscCall(MPIU_Allreduce(&eventInfo[event].CpuToGpuCount, &cct, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2365         PetscCall(MPIU_Allreduce(&eventInfo[event].GpuToCpuCount, &gct, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2366         PetscCall(MPIU_Allreduce(&eventInfo[event].CpuToGpuSize, &csz, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2367         PetscCall(MPIU_Allreduce(&eventInfo[event].GpuToCpuSize, &gsz, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2368         PetscCall(MPIU_Allreduce(&eventInfo[event].GpuFlops, &gflops, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2369         PetscCall(MPIU_Allreduce(&eventInfo[event].GpuTime, &gmaxt, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2370   #endif
2371         name = stageLog->eventLog->eventInfo[event].name;
2372       } else {
2373         int ierr = 0;
2374 
2375         flopr = 0.0;
2376         PetscCall(MPIU_Allreduce(&flopr, &minf, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm));
2377         PetscCall(MPIU_Allreduce(&flopr, &maxf, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2378         PetscCall(MPIU_Allreduce(&zero, &totf, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2379         PetscCall(MPIU_Allreduce(&zero, &mint, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, comm));
2380         PetscCall(MPIU_Allreduce(&zero, &maxt, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2381         PetscCall(MPIU_Allreduce(&zero, &tott, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2382         PetscCall(MPIU_Allreduce(&zero, &totm, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2383         PetscCall(MPIU_Allreduce(&zero, &totml, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2384         PetscCall(MPIU_Allreduce(&zero, &totr, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2385         PetscCallMPI(MPI_Allreduce(&ierr, &minC, 1, MPI_INT, MPI_MIN, comm));
2386         PetscCallMPI(MPI_Allreduce(&ierr, &maxC, 1, MPI_INT, MPI_MAX, comm));
2387         if (PetscLogMemory) {
2388           PetscCall(MPIU_Allreduce(&zero, &mem, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2389           PetscCall(MPIU_Allreduce(&zero, &mal, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2390           PetscCall(MPIU_Allreduce(&zero, &malmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2391           PetscCall(MPIU_Allreduce(&zero, &emalmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2392         }
2393   #if defined(PETSC_HAVE_DEVICE)
2394         PetscCall(MPIU_Allreduce(&zero, &cct, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2395         PetscCall(MPIU_Allreduce(&zero, &gct, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2396         PetscCall(MPIU_Allreduce(&zero, &csz, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2397         PetscCall(MPIU_Allreduce(&zero, &gsz, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2398         PetscCall(MPIU_Allreduce(&zero, &gflops, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, comm));
2399         PetscCall(MPIU_Allreduce(&zero, &gmaxt, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, comm));
2400   #endif
2401         name = "";
2402       }
2403       if (mint < 0.0) {
2404         PetscCall(PetscFPrintf(comm, fd, "WARNING!!! Minimum time %g over all processors for %s is negative! This happens\n on some machines whose times cannot handle too rapid calls.!\n artificially changing minimum to zero.\n", mint, name));
2405         mint = 0;
2406       }
2407       PetscCheck(minf >= 0.0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Minimum flop %g over all processors for %s is negative! Not possible!", minf, name);
2408   /* Put NaN into the time for all events that may not be time accurately since they may happen asynchronously on the GPU */
2409   #if defined(PETSC_HAVE_DEVICE)
2410       if (!PetscLogGpuTimeFlag && petsc_gflops > 0) {
2411         memcpy(&gmaxt, &nas, sizeof(PetscLogDouble));
2412         PetscCall(PetscEventRegLogGetEvent(stageLog->eventLog, name, &eventid));
2413         if (eventid != SNES_Solve && eventid != KSP_Solve && eventid != TS_Step && eventid != TAO_Solve) {
2414           memcpy(&mint, &nas, sizeof(PetscLogDouble));
2415           memcpy(&maxt, &nas, sizeof(PetscLogDouble));
2416         }
2417       }
2418   #endif
2419       totm *= 0.5;
2420       totml *= 0.5;
2421       totr /= size;
2422 
2423       if (maxC != 0) {
2424         if (minC != 0) ratC = ((PetscLogDouble)maxC) / minC;
2425         else ratC = 0.0;
2426         if (mint != 0.0) ratt = maxt / mint;
2427         else ratt = 0.0;
2428         if (minf != 0.0) ratf = maxf / minf;
2429         else ratf = 0.0;
2430         if (TotalTime != 0.0) fracTime = tott / TotalTime;
2431         else fracTime = 0.0;
2432         if (TotalFlops != 0.0) fracFlops = totf / TotalFlops;
2433         else fracFlops = 0.0;
2434         if (stageTime != 0.0) fracStageTime = tott / stageTime;
2435         else fracStageTime = 0.0;
2436         if (flops != 0.0) fracStageFlops = totf / flops;
2437         else fracStageFlops = 0.0;
2438         if (numMessages != 0.0) fracMess = totm / numMessages;
2439         else fracMess = 0.0;
2440         if (messageLength != 0.0) fracMessLen = totml / messageLength;
2441         else fracMessLen = 0.0;
2442         if (numReductions != 0.0) fracRed = totr / numReductions;
2443         else fracRed = 0.0;
2444         if (mess != 0.0) fracStageMess = totm / mess;
2445         else fracStageMess = 0.0;
2446         if (messLen != 0.0) fracStageMessLen = totml / messLen;
2447         else fracStageMessLen = 0.0;
2448         if (red != 0.0) fracStageRed = totr / red;
2449         else fracStageRed = 0.0;
2450         if (totm != 0.0) totml /= totm;
2451         else totml = 0.0;
2452         if (maxt != 0.0) flopr = totf / maxt;
2453         else flopr = 0.0;
2454         if (fracStageTime > 1.0 || fracStageFlops > 1.0 || fracStageMess > 1.0 || fracStageMessLen > 1.0 || fracStageRed > 1.0)
2455           PetscCall(PetscFPrintf(comm, fd, "%-16s %7d %3.1f %5.4e %3.1f %3.2e %3.1f %2.1e %2.1e %2.1e %2.0f %2.0f %2.0f %2.0f %2.0f Multiple stages %5.0f", name, maxC, ratC, maxt, ratt, maxf, ratf, totm, totml, totr, 100.0 * fracTime, 100.0 * fracFlops, 100.0 * fracMess, 100.0 * fracMessLen, 100.0 * fracRed, PetscAbs(flopr) / 1.0e6));
2456         else
2457           PetscCall(PetscFPrintf(comm, fd, "%-16s %7d %3.1f %5.4e %3.1f %3.2e %3.1f %2.1e %2.1e %2.1e %2.0f %2.0f %2.0f %2.0f %2.0f %3.0f %2.0f %2.0f %2.0f %2.0f %5.0f", name, maxC, ratC, maxt, ratt, maxf, ratf, totm, totml, totr, 100.0 * fracTime, 100.0 * fracFlops, 100.0 * fracMess, 100.0 * fracMessLen, 100.0 * fracRed, 100.0 * fracStageTime, 100.0 * fracStageFlops, 100.0 * fracStageMess, 100.0 * fracStageMessLen, 100.0 * fracStageRed, PetscAbs(flopr) / 1.0e6));
2458         if (PetscLogMemory) PetscCall(PetscFPrintf(comm, fd, " %5.0f   %5.0f   %5.0f   %5.0f", mal / 1.0e6, emalmax / 1.0e6, malmax / 1.0e6, mem / 1.0e6));
2459   #if defined(PETSC_HAVE_DEVICE)
2460         if (totf != 0.0) fracgflops = gflops / totf;
2461         else fracgflops = 0.0;
2462         if (gmaxt != 0.0) gflopr = gflops / gmaxt;
2463         else gflopr = 0.0;
2464         PetscCall(PetscFPrintf(comm, fd, "   %5.0f   %4.0f %3.2e %4.0f %3.2e % 2.0f", PetscAbs(gflopr) / 1.0e6, cct / size, csz / (1.0e6 * size), gct / size, gsz / (1.0e6 * size), 100.0 * fracgflops));
2465   #endif
2466         PetscCall(PetscFPrintf(comm, fd, "\n"));
2467       }
2468     }
2469   }
2470 
2471   /* Memory usage and object creation */
2472   PetscCall(PetscFPrintf(comm, fd, "------------------------------------------------------------------------------------------------------------------------"));
2473   if (PetscLogMemory) PetscCall(PetscFPrintf(comm, fd, "-----------------------------"));
2474   #if defined(PETSC_HAVE_DEVICE)
2475   PetscCall(PetscFPrintf(comm, fd, "---------------------------------------"));
2476   #endif
2477   PetscCall(PetscFPrintf(comm, fd, "\n"));
2478   PetscCall(PetscFPrintf(comm, fd, "\n"));
2479 
2480   /* Right now, only stages on the first processor are reported here, meaning only objects associated with
2481      the global communicator, or MPI_COMM_SELF for proc 1. We really should report global stats and then
2482      stats for stages local to processor sets.
2483   */
2484   /* We should figure out the longest object name here (now 20 characters) */
2485   PetscCall(PetscFPrintf(comm, fd, "Object Type          Creations   Destructions. Reports information only for process 0.\n"));
2486   for (stage = 0; stage < numStages; stage++) {
2487     if (localStageUsed[stage]) {
2488       classInfo = stageLog->stageInfo[stage].classLog->classInfo;
2489       PetscCall(PetscFPrintf(comm, fd, "\n--- Event Stage %d: %s\n\n", stage, stageInfo[stage].name));
2490       for (oclass = 0; oclass < stageLog->stageInfo[stage].classLog->numClasses; oclass++) {
2491         if ((classInfo[oclass].creations > 0) || (classInfo[oclass].destructions > 0)) {
2492           PetscCall(PetscFPrintf(comm, fd, "%20s %5d          %5d\n", stageLog->classLog->classInfo[oclass].name, classInfo[oclass].creations, classInfo[oclass].destructions));
2493         }
2494       }
2495     } else {
2496       if (!localStageVisible[stage]) continue;
2497       PetscCall(PetscFPrintf(comm, fd, "\n--- Event Stage %d: Unknown\n\n", stage));
2498     }
2499   }
2500 
2501   PetscCall(PetscFree(localStageUsed));
2502   PetscCall(PetscFree(stageUsed));
2503   PetscCall(PetscFree(localStageVisible));
2504   PetscCall(PetscFree(stageVisible));
2505 
2506   /* Information unrelated to this particular run */
2507   PetscCall(PetscFPrintf(comm, fd, "========================================================================================================================\n"));
2508   PetscCall(PetscTime(&y));
2509   PetscCall(PetscTime(&x));
2510   PetscCall(PetscTime(&y));
2511   PetscCall(PetscTime(&y));
2512   PetscCall(PetscTime(&y));
2513   PetscCall(PetscTime(&y));
2514   PetscCall(PetscTime(&y));
2515   PetscCall(PetscTime(&y));
2516   PetscCall(PetscTime(&y));
2517   PetscCall(PetscTime(&y));
2518   PetscCall(PetscTime(&y));
2519   PetscCall(PetscTime(&y));
2520   PetscCall(PetscFPrintf(comm, fd, "Average time to get PetscTime(): %g\n", (y - x) / 10.0));
2521   /* MPI information */
2522   if (size > 1) {
2523     MPI_Status  status;
2524     PetscMPIInt tag;
2525     MPI_Comm    newcomm;
2526 
2527     PetscCallMPI(MPI_Barrier(comm));
2528     PetscCall(PetscTime(&x));
2529     PetscCallMPI(MPI_Barrier(comm));
2530     PetscCallMPI(MPI_Barrier(comm));
2531     PetscCallMPI(MPI_Barrier(comm));
2532     PetscCallMPI(MPI_Barrier(comm));
2533     PetscCallMPI(MPI_Barrier(comm));
2534     PetscCall(PetscTime(&y));
2535     PetscCall(PetscFPrintf(comm, fd, "Average time for MPI_Barrier(): %g\n", (y - x) / 5.0));
2536     PetscCall(PetscCommDuplicate(comm, &newcomm, &tag));
2537     PetscCallMPI(MPI_Barrier(comm));
2538     if (rank) {
2539       PetscCallMPI(MPI_Recv(NULL, 0, MPI_INT, rank - 1, tag, newcomm, &status));
2540       PetscCallMPI(MPI_Send(NULL, 0, MPI_INT, (rank + 1) % size, tag, newcomm));
2541     } else {
2542       PetscCall(PetscTime(&x));
2543       PetscCallMPI(MPI_Send(NULL, 0, MPI_INT, 1, tag, newcomm));
2544       PetscCallMPI(MPI_Recv(NULL, 0, MPI_INT, size - 1, tag, newcomm, &status));
2545       PetscCall(PetscTime(&y));
2546       PetscCall(PetscFPrintf(comm, fd, "Average time for zero size MPI_Send(): %g\n", (y - x) / size));
2547     }
2548     PetscCall(PetscCommDestroy(&newcomm));
2549   }
2550   PetscCall(PetscOptionsView(NULL, viewer));
2551 
2552   /* Machine and compile information */
2553   #if defined(PETSC_USE_FORTRAN_KERNELS)
2554   PetscCall(PetscFPrintf(comm, fd, "Compiled with FORTRAN kernels\n"));
2555   #else
2556   PetscCall(PetscFPrintf(comm, fd, "Compiled without FORTRAN kernels\n"));
2557   #endif
2558   #if defined(PETSC_USE_64BIT_INDICES)
2559   PetscCall(PetscFPrintf(comm, fd, "Compiled with 64-bit PetscInt\n"));
2560   #elif defined(PETSC_USE___FLOAT128)
2561   PetscCall(PetscFPrintf(comm, fd, "Compiled with 32-bit PetscInt\n"));
2562   #endif
2563   #if defined(PETSC_USE_REAL_SINGLE)
2564   PetscCall(PetscFPrintf(comm, fd, "Compiled with single precision PetscScalar and PetscReal\n"));
2565   #elif defined(PETSC_USE___FLOAT128)
2566   PetscCall(PetscFPrintf(comm, fd, "Compiled with 128 bit precision PetscScalar and PetscReal\n"));
2567   #endif
2568   #if defined(PETSC_USE_REAL_MAT_SINGLE)
2569   PetscCall(PetscFPrintf(comm, fd, "Compiled with single precision matrices\n"));
2570   #else
2571   PetscCall(PetscFPrintf(comm, fd, "Compiled with full precision matrices (default)\n"));
2572   #endif
2573   PetscCall(PetscFPrintf(comm, fd, "sizeof(short) %d sizeof(int) %d sizeof(long) %d sizeof(void*) %d sizeof(PetscScalar) %d sizeof(PetscInt) %d\n", (int)sizeof(short), (int)sizeof(int), (int)sizeof(long), (int)sizeof(void *), (int)sizeof(PetscScalar), (int)sizeof(PetscInt)));
2574 
2575   PetscCall(PetscFPrintf(comm, fd, "Configure options: %s", petscconfigureoptions));
2576   PetscCall(PetscFPrintf(comm, fd, "%s", petscmachineinfo));
2577   PetscCall(PetscFPrintf(comm, fd, "%s", petsccompilerinfo));
2578   PetscCall(PetscFPrintf(comm, fd, "%s", petsccompilerflagsinfo));
2579   PetscCall(PetscFPrintf(comm, fd, "%s", petsclinkerinfo));
2580 
2581   /* Cleanup */
2582   PetscCall(PetscFPrintf(comm, fd, "\n"));
2583   PetscCall(PetscLogViewWarnNoGpuAwareMpi(comm, fd));
2584   PetscCall(PetscLogViewWarnDebugging(comm, fd));
2585   PetscCall(PetscFPTrapPop());
2586   PetscFunctionReturn(PETSC_SUCCESS);
2587 }
2588 
2589 /*@C
2590   PetscLogView - Prints a summary of the logging.
2591 
2592   Collective over MPI_Comm
2593 
2594   Input Parameter:
2595 . viewer - an ASCII viewer
2596 
2597   Options Database Keys:
2598 + -log_view [:filename]                    - Prints summary of log information
2599 . -log_view :filename.py:ascii_info_detail - Saves logging information from each process as a Python file
2600 . -log_view :filename.xml:ascii_xml        - Saves a summary of the logging information in a nested format (see below for how to view it)
2601 . -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)
2602 . -log_view_memory                         - Also display memory usage in each event
2603 . -log_view_gpu_time                       - Also display time in each event for GPU kernels (Note this may slow the computation)
2604 . -log_all                                 - Saves a file Log.rank for each MPI rank with details of each step of the computation
2605 - -log_trace [filename]                    - Displays a trace of what each process is doing
2606 
2607   Level: beginner
2608 
2609   Notes:
2610   It is possible to control the logging programmatically but we recommend using the options database approach whenever possible
2611   By default the summary is printed to stdout.
2612 
2613   Before calling this routine you must have called either PetscLogDefaultBegin() or PetscLogNestedBegin()
2614 
2615   If PETSc is configured with --with-logging=0 then this functionality is not available
2616 
2617   To view the nested XML format filename.xml first copy  ${PETSC_DIR}/share/petsc/xml/performance_xml2html.xsl to the current
2618   directory then open filename.xml with your browser. Specific notes for certain browsers
2619 $    Firefox and Internet explorer - simply open the file
2620 $    Google Chrome - you must start up Chrome with the option --allow-file-access-from-files
2621 $    Safari - see https://ccm.net/faq/36342-safari-how-to-enable-local-file-access
2622   or one can use the package http://xmlsoft.org/XSLT/xsltproc2.html to translate the xml file to html and then open it with
2623   your browser.
2624   Alternatively, use the script ${PETSC_DIR}/lib/petsc/bin/petsc-performance-view to automatically open a new browser
2625   window and render the XML log file contents.
2626 
2627   The nested XML format was kindly donated by Koos Huijssen and Christiaan M. Klaij  MARITIME  RESEARCH  INSTITUTE  NETHERLANDS
2628 
2629   The Flame Graph output can be visualised using either the original Flame Graph script (https://github.com/brendangregg/FlameGraph)
2630   or using speedscope (https://www.speedscope.app).
2631   Old XML profiles may be converted into this format using the script ${PETSC_DIR}/lib/petsc/bin/xml2flamegraph.py.
2632 
2633 .seealso: [](ch_profiling), `PetscLogDefaultBegin()`, `PetscLogDump()`
2634 @*/
2635 PetscErrorCode PetscLogView(PetscViewer viewer)
2636 {
2637   PetscBool         isascii;
2638   PetscViewerFormat format;
2639   int               stage, lastStage;
2640   PetscStageLog     stageLog;
2641 
2642   PetscFunctionBegin;
2643   PetscCheck(PetscLogPLB, PETSC_COMM_SELF, PETSC_ERR_SUP, "Must use -log_view or PetscLogDefaultBegin() before calling this routine");
2644   /* Pop off any stages the user forgot to remove */
2645   lastStage = 0;
2646   PetscCall(PetscLogGetStageLog(&stageLog));
2647   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
2648   while (stage >= 0) {
2649     lastStage = stage;
2650     PetscCall(PetscStageLogPop(stageLog));
2651     PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
2652   }
2653   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2654   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Currently can only view logging to ASCII");
2655   PetscCall(PetscViewerGetFormat(viewer, &format));
2656   if (format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_ASCII_INFO) {
2657     PetscCall(PetscLogView_Default(viewer));
2658   } else if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
2659     PetscCall(PetscLogView_Detailed(viewer));
2660   } else if (format == PETSC_VIEWER_ASCII_CSV) {
2661     PetscCall(PetscLogView_CSV(viewer));
2662   } else if (format == PETSC_VIEWER_ASCII_XML) {
2663     PetscCall(PetscLogView_Nested(viewer));
2664   } else if (format == PETSC_VIEWER_ASCII_FLAMEGRAPH) {
2665     PetscCall(PetscLogView_Flamegraph(viewer));
2666   }
2667   PetscCall(PetscStageLogPush(stageLog, lastStage));
2668   PetscFunctionReturn(PETSC_SUCCESS);
2669 }
2670 
2671 /*@C
2672   PetscLogViewFromOptions - Processes command line options to determine if/how a `PetscLog` is to be viewed.
2673 
2674   Collective on `PETSC_COMM_WORLD`
2675 
2676   Level: developer
2677 
2678 .seealso: [](ch_profiling), `PetscLogView()`
2679 @*/
2680 PetscErrorCode PetscLogViewFromOptions(void)
2681 {
2682   PetscViewer       viewer;
2683   PetscBool         flg;
2684   PetscViewerFormat format;
2685 
2686   PetscFunctionBegin;
2687   PetscCall(PetscOptionsGetViewer(PETSC_COMM_WORLD, NULL, NULL, "-log_view", &viewer, &format, &flg));
2688   if (flg) {
2689     PetscCall(PetscViewerPushFormat(viewer, format));
2690     PetscCall(PetscLogView(viewer));
2691     PetscCall(PetscViewerPopFormat(viewer));
2692     PetscCall(PetscViewerDestroy(&viewer));
2693   }
2694   PetscFunctionReturn(PETSC_SUCCESS);
2695 }
2696 
2697 /*----------------------------------------------- Counter Functions -------------------------------------------------*/
2698 /*@C
2699   PetscGetFlops - Returns the number of flops used on this processor
2700   since the program began.
2701 
2702   Not Collective
2703 
2704   Output Parameter:
2705 . flops - number of floating point operations
2706 
2707   Level: intermediate
2708 
2709   Notes:
2710   A global counter logs all PETSc flop counts.  The user can use
2711   `PetscLogFlops()` to increment this counter to include flops for the
2712   application code.
2713 
2714   A separate counter `PetscLogGPUFlops()` logs the flops that occur on any GPU associated with this MPI rank
2715 
2716 .seealso: [](ch_profiling), `PetscLogGPUFlops()`, `PetscTime()`, `PetscLogFlops()`
2717 @*/
2718 PetscErrorCode PetscGetFlops(PetscLogDouble *flops)
2719 {
2720   PetscFunctionBegin;
2721   *flops = petsc_TotalFlops;
2722   PetscFunctionReturn(PETSC_SUCCESS);
2723 }
2724 
2725 /*@C
2726   PetscLogObjectState - Record information about an object with the default log handler
2727 
2728   Not Collective
2729 
2730   Input Parameters:
2731 + obj    - the `PetscObject`
2732 . format - a printf-style format string
2733 - ...    - printf arguments to format
2734 
2735   Level: developer
2736 
2737 .seealso: [](ch_profiling), `PetscLogObjectCreate()`, `PetscLogObjectDestroy()`
2738 @*/
2739 PetscErrorCode PetscLogObjectState(PetscObject obj, const char format[], ...)
2740 {
2741   size_t  fullLength;
2742   va_list Argp;
2743 
2744   PetscFunctionBegin;
2745   if (!petsc_logObjects) PetscFunctionReturn(PETSC_SUCCESS);
2746   va_start(Argp, format);
2747   PetscCall(PetscVSNPrintf(petsc_objects[obj->id].info, 64, format, &fullLength, Argp));
2748   va_end(Argp);
2749   PetscFunctionReturn(PETSC_SUCCESS);
2750 }
2751 
2752 /*MC
2753   PetscLogFlops - Adds floating point operations to the global counter.
2754 
2755   Synopsis:
2756   #include <petsclog.h>
2757   PetscErrorCode PetscLogFlops(PetscLogDouble f)
2758 
2759   Not Collective
2760 
2761   Input Parameter:
2762 . f - flop counter
2763 
2764   Example Usage:
2765 .vb
2766   PetscLogEvent USER_EVENT;
2767 
2768   PetscLogEventRegister("User event", 0, &USER_EVENT);
2769   PetscLogEventBegin(USER_EVENT, 0, 0, 0, 0);
2770   [code segment to monitor]
2771   PetscLogFlops(user_flops)
2772   PetscLogEventEnd(USER_EVENT, 0, 0, 0, 0);
2773 .ve
2774 
2775   Level: intermediate
2776 
2777   Note:
2778    A global counter logs all PETSc flop counts. The user can use PetscLogFlops() to increment
2779    this counter to include flops for the application code.
2780 
2781 .seealso: [](ch_profiling), `PetscLogGPUFlops()`, `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscGetFlops()`
2782 M*/
2783 
2784 /*MC
2785   PetscPreLoadBegin - Begin a segment of code that may be preloaded (run twice) to get accurate
2786   timings
2787 
2788   Synopsis:
2789   #include <petsclog.h>
2790   void PetscPreLoadBegin(PetscBool flag, char *name);
2791 
2792   Not Collective
2793 
2794   Input Parameters:
2795 + flag - `PETSC_TRUE` to run twice, `PETSC_FALSE` to run once, may be overridden with command
2796          line option `-preload true|false`
2797 - name - name of first stage (lines of code timed separately with `-log_view`) to be preloaded
2798 
2799   Example Usage:
2800 .vb
2801   PetscPreLoadBegin(PETSC_TRUE, "first stage");
2802   // lines of code
2803   PetscPreLoadStage("second stage");
2804   // lines of code
2805   PetscPreLoadEnd();
2806 .ve
2807 
2808   Level: intermediate
2809 
2810   Note:
2811   Only works in C/C++, not Fortran
2812 
2813   Flags available within the macro\:
2814 + PetscPreLoadingUsed - `PETSC_TRUE` if we are or have done preloading
2815 . PetscPreLoadingOn   - `PETSC_TRUE` if it is CURRENTLY doing preload
2816 . PetscPreLoadIt      - `0` for the first computation (with preloading turned off it is only
2817                         `0`) `1`  for the second
2818 - PetscPreLoadMax     - number of times it will do the computation, only one when preloading is
2819                         turned on
2820 
2821   The first two variables are available throughout the program, the second two only between the
2822   `PetscPreLoadBegin()` and `PetscPreLoadEnd()`
2823 
2824 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadEnd()`, `PetscPreLoadStage()`
2825 M*/
2826 
2827 /*MC
2828   PetscPreLoadEnd - End a segment of code that may be preloaded (run twice) to get accurate
2829   timings
2830 
2831   Synopsis:
2832   #include <petsclog.h>
2833   void PetscPreLoadEnd(void);
2834 
2835   Not Collective
2836 
2837   Example Usage:
2838 .vb
2839   PetscPreLoadBegin(PETSC_TRUE, "first stage");
2840   // lines of code
2841   PetscPreLoadStage("second stage");
2842   // lines of code
2843   PetscPreLoadEnd();
2844 .ve
2845 
2846   Level: intermediate
2847 
2848   Note:
2849   Only works in C/C++ not fortran
2850 
2851 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadStage()`
2852 M*/
2853 
2854 /*MC
2855   PetscPreLoadStage - Start a new segment of code to be timed separately to get accurate timings
2856 
2857   Synopsis:
2858   #include <petsclog.h>
2859   void PetscPreLoadStage(char *name);
2860 
2861   Not Collective
2862 
2863   Example Usage:
2864 .vb
2865   PetscPreLoadBegin(PETSC_TRUE,"first stage");
2866   // lines of code
2867   PetscPreLoadStage("second stage");
2868   // lines of code
2869   PetscPreLoadEnd();
2870 .ve
2871 
2872   Level: intermediate
2873 
2874   Note:
2875   Only works in C/C++ not fortran
2876 
2877 .seealso: [](ch_profiling), `PetscLogEventRegister()`, `PetscLogEventBegin()`, `PetscLogEventEnd()`, `PetscPreLoadBegin()`, `PetscPreLoadEnd()`
2878 M*/
2879 
2880   #if PetscDefined(HAVE_DEVICE)
2881     #include <petsc/private/deviceimpl.h>
2882 
2883 /*
2884    This cannot be called by users between PetscInitialize() and PetscFinalize() at any random location in the code
2885    because it will result in timing results that cannot be interpreted.
2886 */
2887 static PetscErrorCode PetscLogGpuTime_Off(void)
2888 {
2889   PetscLogGpuTimeFlag = PETSC_FALSE;
2890   return PETSC_SUCCESS;
2891 }
2892 
2893 /*@C
2894   PetscLogGpuTime - turn on the logging of GPU time for GPU kernels
2895 
2896   Options Database Key:
2897 . -log_view_gpu_time - provide the GPU times in the `-log_view` output
2898 
2899   Level: advanced
2900 
2901   Notes:
2902   Turning on the timing of the GPU kernels can slow down the entire computation and should only
2903   be used when studying the performance of operations on GPU such as vector operations and
2904   matrix-vector operations.
2905 
2906   This routine should only be called once near the beginning of the program. Once it is started
2907   it cannot be turned off.
2908 
2909 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTimeBegin()`
2910 @*/
2911 PetscErrorCode PetscLogGpuTime(void)
2912 {
2913   if (!PetscLogGpuTimeFlag) PetscCall(PetscRegisterFinalize(PetscLogGpuTime_Off));
2914   PetscLogGpuTimeFlag = PETSC_TRUE;
2915   return PETSC_SUCCESS;
2916 }
2917 
2918 /*@C
2919   PetscLogGpuTimeBegin - Start timer for device
2920 
2921   Level: intermediate
2922 
2923   Notes:
2924   When CUDA or HIP is enabled, the timer is run on the GPU, it is a separate logging of time
2925   devoted to GPU computations (excluding kernel launch times).
2926 
2927   When CUDA or HIP is not available, the timer is run on the CPU, it is a separate logging of
2928   time devoted to GPU computations (including kernel launch times).
2929 
2930   There is no need to call WaitForCUDA() or WaitForHIP() between `PetscLogGpuTimeBegin()` and
2931   `PetscLogGpuTimeEnd()`
2932 
2933   This timer should NOT include times for data transfers between the GPU and CPU, nor setup
2934   actions such as allocating space.
2935 
2936   The regular logging captures the time for data transfers and any CPU activities during the
2937   event. It is used to compute the flop rate on the GPU as it is actively engaged in running a
2938   kernel.
2939 
2940   Developer Notes:
2941   The GPU event timer captures the execution time of all the kernels launched in the default
2942   stream by the CPU between `PetscLogGpuTimeBegin()` and `PetsLogGpuTimeEnd()`.
2943 
2944   `PetscLogGpuTimeBegin()` and `PetsLogGpuTimeEnd()` insert the begin and end events into the
2945   default stream (stream 0). The device will record a time stamp for the event when it reaches
2946   that event in the stream. The function xxxEventSynchronize() is called in
2947   `PetsLogGpuTimeEnd()` to block CPU execution, but not continued GPU execution, until the
2948   timer event is recorded.
2949 
2950 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeEnd()`, `PetscLogGpuTime()`
2951 @*/
2952 PetscErrorCode PetscLogGpuTimeBegin(void)
2953 {
2954   PetscFunctionBegin;
2955   if (!PetscLogPLB || !PetscLogGpuTimeFlag) PetscFunctionReturn(PETSC_SUCCESS);
2956   if (PetscDefined(HAVE_DEVICE)) {
2957     PetscDeviceContext dctx;
2958 
2959     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2960     PetscCall(PetscDeviceContextBeginTimer_Internal(dctx));
2961   } else {
2962     PetscCall(PetscTimeSubtract(&petsc_gtime));
2963   }
2964   PetscFunctionReturn(PETSC_SUCCESS);
2965 }
2966 
2967 /*@C
2968   PetscLogGpuTimeEnd - Stop timer for device
2969 
2970   Level: intermediate
2971 
2972 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`, `PetscLogGpuTimeBegin()`
2973 @*/
2974 PetscErrorCode PetscLogGpuTimeEnd(void)
2975 {
2976   PetscFunctionBegin;
2977   if (!PetscLogPLE || !PetscLogGpuTimeFlag) PetscFunctionReturn(PETSC_SUCCESS);
2978   if (PetscDefined(HAVE_DEVICE)) {
2979     PetscDeviceContext dctx;
2980     PetscLogDouble     elapsed;
2981 
2982     PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
2983     PetscCall(PetscDeviceContextEndTimer_Internal(dctx, &elapsed));
2984     petsc_gtime += (elapsed / 1000.0);
2985   } else {
2986     PetscCall(PetscTimeAdd(&petsc_gtime));
2987   }
2988   PetscFunctionReturn(PETSC_SUCCESS);
2989 }
2990 
2991   #endif /* end of PETSC_HAVE_DEVICE */
2992 
2993 #endif /* PETSC_USE_LOG*/
2994 
2995 PetscClassId PETSC_LARGEST_CLASSID = PETSC_SMALLEST_CLASSID;
2996 PetscClassId PETSC_OBJECT_CLASSID  = 0;
2997 
2998 /* Logging functions */
2999 PetscErrorCode (*PetscLogPHC)(PetscObject)                                                            = NULL;
3000 PetscErrorCode (*PetscLogPHD)(PetscObject)                                                            = NULL;
3001 PetscErrorCode (*PetscLogPLB)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject) = NULL;
3002 PetscErrorCode (*PetscLogPLE)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject) = NULL;
3003 
3004 /* Tracing event logging variables */
3005 FILE            *petsc_tracefile          = NULL;
3006 int              petsc_tracelevel         = 0;
3007 const char      *petsc_traceblanks        = "                                                                                                    ";
3008 char             petsc_tracespace[128]    = " ";
3009 PetscLogDouble   petsc_tracetime          = 0.0;
3010 static PetscBool PetscLogInitializeCalled = PETSC_FALSE;
3011 
3012 static PetscIntStack current_log_event_stack = NULL;
3013 
3014 PETSC_INTERN PetscErrorCode PetscLogInitialize(void)
3015 {
3016   int       stage;
3017   PetscBool opt;
3018 
3019   PetscFunctionBegin;
3020   if (PetscLogInitializeCalled) PetscFunctionReturn(PETSC_SUCCESS);
3021   PetscLogInitializeCalled = PETSC_TRUE;
3022   if (PetscDefined(USE_LOG)) {
3023     PetscCall(PetscIntStackCreate(&current_log_event_stack));
3024     PetscCall(PetscOptionsHasName(NULL, NULL, "-log_exclude_actions", &opt));
3025     if (opt) petsc_logActions = PETSC_FALSE;
3026     PetscCall(PetscOptionsHasName(NULL, NULL, "-log_exclude_objects", &opt));
3027     if (opt) petsc_logObjects = PETSC_FALSE;
3028     if (petsc_logActions) PetscCall(PetscMalloc1(petsc_maxActions, &petsc_actions));
3029     if (petsc_logObjects) PetscCall(PetscMalloc1(petsc_maxObjects, &petsc_objects));
3030     PetscLogPHC = PetscLogObjCreateDefault;
3031     PetscLogPHD = PetscLogObjDestroyDefault;
3032     /* Setup default logging structures */
3033     PetscCall(PetscLogStateCreate(&petsc_log_state));
3034     for (PetscInt i = 0; i < PETSC_LOG_HANDLER_MAX; i++) {
3035       if (PetscLogHandlers[i].handler) PetscCall(PetscLogHandlerSetState(PetscLogHandlers[i].handler, petsc_log_state));
3036     }
3037     PetscCall(PetscLogStateStageRegister(petsc_log_state, "Main Stage", &stage));
3038     PetscCall(PetscStageLogCreate(&petsc_stageLog));
3039     PetscCall(PetscStageLogRegister(petsc_stageLog, "Main Stage", &stage));
3040 
3041     PetscCall(PetscSpinlockCreate(&PetscLogSpinLock));
3042 #if defined(PETSC_HAVE_THREADSAFETY)
3043     petsc_log_tid = 0;
3044     petsc_log_gid = 0;
3045     PetscCall(PetscHMapEventCreate(&eventInfoMap_th));
3046 #endif
3047 
3048     /* All processors sync here for more consistent logging */
3049     PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
3050     PetscCall(PetscTime(&petsc_BaseTime));
3051     PetscCall(PetscLogStagePush(stage));
3052   #if defined(PETSC_HAVE_TAU_PERFSTUBS)
3053     PetscStackCallExternalVoid("ps_initialize_", ps_initialize_());
3054   #endif
3055   }
3056   PetscFunctionReturn(PETSC_SUCCESS);
3057 }
3058 
3059 PETSC_INTERN PetscErrorCode PetscLogFinalize(void)
3060 {
3061   PetscStageLog stageLog;
3062 
3063   PetscFunctionBegin;
3064   if (PetscDefined(USE_LOG)) {
3065     for (int i = 0; i < PETSC_LOG_HANDLER_MAX; i++) PetscCall(PetscLogHandlerDestroy(&PetscLogHandlers[i].handler));
3066     PetscCall(PetscArrayzero(PetscLogHandlers, PETSC_LOG_HANDLER_MAX));
3067     PetscCall(PetscLogStateDestroy(&petsc_log_state));
3068   #if defined(PETSC_HAVE_THREADSAFETY)
3069     if (eventInfoMap_th) {
3070       PetscEventPerfInfo **array;
3071       PetscInt             n, off = 0;
3072 
3073       PetscCall(PetscHMapEventGetSize(eventInfoMap_th, &n));
3074       PetscCall(PetscMalloc1(n, &array));
3075       PetscCall(PetscHMapEventGetVals(eventInfoMap_th, &off, array));
3076       for (PetscInt i = 0; i < n; i++) PetscCall(PetscFree(array[i]));
3077       PetscCall(PetscFree(array));
3078       PetscCall(PetscHMapEventDestroy(&eventInfoMap_th));
3079     }
3080   #endif
3081     PetscCall(PetscFree(petsc_actions));
3082     PetscCall(PetscFree(petsc_objects));
3083     PetscCall(PetscLogNestedEnd());
3084     PetscCall(PetscLogSet(NULL, NULL));
3085 
3086     /* Resetting phase */
3087     PetscCall(PetscLogGetStageLog(&stageLog));
3088     PetscCall(PetscStageLogDestroy(stageLog));
3089     PetscCall(PetscIntStackDestroy(current_log_event_stack));
3090     current_log_event_stack = NULL;
3091 
3092     petsc_TotalFlops          = 0.0;
3093     petsc_numActions          = 0;
3094     petsc_numObjects          = 0;
3095     petsc_numObjectsDestroyed = 0;
3096     petsc_maxActions          = 100;
3097     petsc_maxObjects          = 100;
3098     petsc_actions             = NULL;
3099     petsc_objects             = NULL;
3100     petsc_logActions          = PETSC_FALSE;
3101     petsc_logObjects          = PETSC_FALSE;
3102     petsc_BaseTime            = 0.0;
3103     petsc_TotalFlops          = 0.0;
3104     petsc_send_ct             = 0.0;
3105     petsc_recv_ct             = 0.0;
3106     petsc_send_len            = 0.0;
3107     petsc_recv_len            = 0.0;
3108     petsc_isend_ct            = 0.0;
3109     petsc_irecv_ct            = 0.0;
3110     petsc_isend_len           = 0.0;
3111     petsc_irecv_len           = 0.0;
3112     petsc_wait_ct             = 0.0;
3113     petsc_wait_any_ct         = 0.0;
3114     petsc_wait_all_ct         = 0.0;
3115     petsc_sum_of_waits_ct     = 0.0;
3116     petsc_allreduce_ct        = 0.0;
3117     petsc_gather_ct           = 0.0;
3118     petsc_scatter_ct          = 0.0;
3119     petsc_TotalFlops_th       = 0.0;
3120     petsc_send_ct_th          = 0.0;
3121     petsc_recv_ct_th          = 0.0;
3122     petsc_send_len_th         = 0.0;
3123     petsc_recv_len_th         = 0.0;
3124     petsc_isend_ct_th         = 0.0;
3125     petsc_irecv_ct_th         = 0.0;
3126     petsc_isend_len_th        = 0.0;
3127     petsc_irecv_len_th        = 0.0;
3128     petsc_wait_ct_th          = 0.0;
3129     petsc_wait_any_ct_th      = 0.0;
3130     petsc_wait_all_ct_th      = 0.0;
3131     petsc_sum_of_waits_ct_th  = 0.0;
3132     petsc_allreduce_ct_th     = 0.0;
3133     petsc_gather_ct_th        = 0.0;
3134     petsc_scatter_ct_th       = 0.0;
3135 
3136     petsc_ctog_ct    = 0.0;
3137     petsc_gtoc_ct    = 0.0;
3138     petsc_ctog_sz    = 0.0;
3139     petsc_gtoc_sz    = 0.0;
3140     petsc_gflops     = 0.0;
3141     petsc_gtime      = 0.0;
3142     petsc_ctog_ct_th = 0.0;
3143     petsc_gtoc_ct_th = 0.0;
3144     petsc_ctog_sz_th = 0.0;
3145     petsc_gtoc_sz_th = 0.0;
3146     petsc_gflops_th  = 0.0;
3147     petsc_gtime_th   = 0.0;
3148 
3149     PETSC_LARGEST_EVENT      = PETSC_EVENT;
3150     PetscLogPHC              = NULL;
3151     PetscLogPHD              = NULL;
3152     petsc_tracefile          = NULL;
3153     petsc_tracelevel         = 0;
3154     petsc_traceblanks        = "                                                                                                    ";
3155     petsc_tracespace[0]      = ' ';
3156     petsc_tracespace[1]      = 0;
3157     petsc_tracetime          = 0.0;
3158     petsc_stageLog           = NULL;
3159   }
3160   PETSC_LARGEST_CLASSID    = PETSC_SMALLEST_CLASSID;
3161   PETSC_OBJECT_CLASSID     = 0;
3162   PetscLogInitializeCalled = PETSC_FALSE;
3163   PetscFunctionReturn(PETSC_SUCCESS);
3164 }
3165 
3166 /*@C
3167   PetscClassIdRegister - Registers a new class name for objects and logging operations in an application code.
3168 
3169   Not Collective
3170 
3171   Input Parameter:
3172 . name - The class name
3173 
3174   Output Parameter:
3175 . oclass - The class id or classid
3176 
3177   Level: developer
3178 
3179 .seealso: [](ch_profiling), `PetscLogEventRegister()`
3180 @*/
3181 PetscErrorCode PetscClassIdRegister(const char name[], PetscClassId *oclass)
3182 {
3183 #if defined(PETSC_USE_LOG)
3184   PetscStageLog stageLog;
3185   PetscInt      stage;
3186 #endif
3187 
3188   PetscFunctionBegin;
3189   *oclass = ++PETSC_LARGEST_CLASSID;
3190 #if defined(PETSC_USE_LOG)
3191   PetscCall(PetscLogGetStageLog(&stageLog));
3192   PetscCall(PetscClassRegLogRegister(stageLog->classLog, name, *oclass));
3193   for (stage = 0; stage < stageLog->numStages; stage++) PetscCall(PetscClassPerfLogEnsureSize(stageLog->stageInfo[stage].classLog, stageLog->classLog->numClasses));
3194 #endif
3195   PetscFunctionReturn(PETSC_SUCCESS);
3196 }
3197 
3198 #if defined(PETSC_USE_LOG) && defined(PETSC_HAVE_MPE)
3199   #include <mpe.h>
3200 
3201 /*@C
3202   PetscLogMPEDump - Dumps the MPE logging info to file for later use with Jumpshot.
3203 
3204   Input Parameter:
3205 . sname - The filename to dump to
3206 
3207   Collective over `PETSC_COMM_WORLD`
3208 
3209   Level: advanced
3210 
3211 .seealso: [](ch_profiling), `PetscLogDump()`, `PetscLogAllBegin()`, `PetscLogMPEBegin()`
3212 @*/
3213 PetscErrorCode PetscLogMPEDump(const char sname[])
3214 {
3215   char name[PETSC_MAX_PATH_LEN];
3216 
3217   PetscFunctionBegin;
3218   if (PetscBeganMPE) {
3219     PetscCall(PetscInfo(0, "Finalizing MPE.\n"));
3220     if (sname) {
3221       PetscCall(PetscStrncpy(name, sname, sizeof(name)));
3222     } else {
3223       PetscCall(PetscGetProgramName(name, sizeof(name)));
3224     }
3225     PetscCall(MPE_Finish_log(name));
3226   } else {
3227     PetscCall(PetscInfo(0, "Not finalizing MPE (not started by PETSc).\n"));
3228   }
3229   PetscFunctionReturn(PETSC_SUCCESS);
3230 }
3231 
3232   #define PETSC_RGB_COLORS_MAX 39
3233 static const char *PetscLogMPERGBColors[PETSC_RGB_COLORS_MAX] = {"OliveDrab:      ", "BlueViolet:     ", "CadetBlue:      ", "CornflowerBlue: ", "DarkGoldenrod:  ", "DarkGreen:      ", "DarkKhaki:      ", "DarkOliveGreen: ",
3234                                                                  "DarkOrange:     ", "DarkOrchid:     ", "DarkSeaGreen:   ", "DarkSlateGray:  ", "DarkTurquoise:  ", "DeepPink:       ", "DarkKhaki:      ", "DimGray:        ",
3235                                                                  "DodgerBlue:     ", "GreenYellow:    ", "HotPink:        ", "IndianRed:      ", "LavenderBlush:  ", "LawnGreen:      ", "LemonChiffon:   ", "LightCoral:     ",
3236                                                                  "LightCyan:      ", "LightPink:      ", "LightSalmon:    ", "LightSlateGray: ", "LightYellow:    ", "LimeGreen:      ", "MediumPurple:   ", "MediumSeaGreen: ",
3237                                                                  "MediumSlateBlue:", "MidnightBlue:   ", "MintCream:      ", "MistyRose:      ", "NavajoWhite:    ", "NavyBlue:       ", "OliveDrab:      "};
3238 
3239 /*@C
3240   PetscLogMPEGetRGBColor - This routine returns a rgb color useable with `PetscLogEventRegister()`
3241 
3242   Not collective. Maybe it should be?
3243 
3244   Output Parameter:
3245 . str - character string representing the color
3246 
3247   Level: developer
3248 
3249 .seealso: [](ch_profiling), `PetscLogEventRegister()`
3250 @*/
3251 PetscErrorCode PetscLogMPEGetRGBColor(const char *str[])
3252 {
3253   static int idx = 0;
3254 
3255   PetscFunctionBegin;
3256   *str = PetscLogMPERGBColors[idx];
3257   idx  = (idx + 1) % PETSC_RGB_COLORS_MAX;
3258   PetscFunctionReturn(PETSC_SUCCESS);
3259 }
3260 
3261 #endif /* PETSC_USE_LOG && PETSC_HAVE_MPE */
3262