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