xref: /petsc/include/petsclog.h (revision 2611ad710242b3c70d66651ef7e40f9450d305e2)
1 /*
2     Defines profile/logging in PETSc.
3 */
4 #ifndef PETSCLOG_H
5 #define PETSCLOG_H
6 
7 #include <petscsys.h>
8 #include <petsctime.h>
9 #include <petscbt.h>
10 #include <petsclogtypes.h>
11 
12 /* SUBMANSEC = Profiling */
13 
14 /* General logging of information; different from event logging */
15 PETSC_EXTERN PetscErrorCode PetscInfo_Private(const char[], PetscObject, const char[], ...) PETSC_ATTRIBUTE_FORMAT(3, 4);
16 #if defined(PETSC_USE_INFO)
17   #define PetscInfo(A, ...) PetscInfo_Private(PETSC_FUNCTION_NAME, ((PetscObject)A), __VA_ARGS__)
18 #else
19   #define PetscInfo(A, ...) PETSC_SUCCESS
20 #endif
21 
22 #define PetscInfo1(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
23 #define PetscInfo2(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
24 #define PetscInfo3(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
25 #define PetscInfo4(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
26 #define PetscInfo5(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
27 #define PetscInfo6(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
28 #define PetscInfo7(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
29 #define PetscInfo8(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
30 #define PetscInfo9(...) PETSC_DEPRECATED_MACRO(3, 17, 0, "PetscInfo()", ) PetscInfo(__VA_ARGS__)
31 
32 /*E
33   PetscInfoCommFlag - Describes the method by which to filter information displayed by `PetscInfo()` by communicator size
34 
35   Values:
36 + `PETSC_INFO_COMM_ALL` - Default uninitialized value. `PetscInfo()` will not filter based on
37                           communicator size (i.e. will print for all communicators)
38 . `PETSC_INFO_COMM_NO_SELF` - `PetscInfo()` will NOT print for communicators with size = 1 (i.e. *_COMM_SELF)
39 - `PETSC_INFO_COMM_ONLY_SELF` - `PetscInfo()` will ONLY print for communicators with size = 1
40 
41   Level: intermediate
42 
43   Note:
44   Used as an input for `PetscInfoSetFilterCommSelf()`
45 
46 .seealso: `PetscInfo()`, `PetscInfoSetFromOptions()`, `PetscInfoSetFilterCommSelf()`
47 E*/
48 typedef enum {
49   PETSC_INFO_COMM_ALL       = -1,
50   PETSC_INFO_COMM_NO_SELF   = 0,
51   PETSC_INFO_COMM_ONLY_SELF = 1
52 } PetscInfoCommFlag;
53 
54 PETSC_EXTERN const char *const PetscInfoCommFlags[];
55 PETSC_EXTERN PetscErrorCode    PetscInfoDeactivateClass(PetscClassId);
56 PETSC_EXTERN PetscErrorCode    PetscInfoActivateClass(PetscClassId);
57 PETSC_EXTERN PetscErrorCode    PetscInfoEnabled(PetscClassId, PetscBool *);
58 PETSC_EXTERN PetscErrorCode    PetscInfoAllow(PetscBool);
59 PETSC_EXTERN PetscErrorCode    PetscInfoSetFile(const char[], const char[]);
60 PETSC_EXTERN PetscErrorCode    PetscInfoGetFile(char **, FILE **);
61 PETSC_EXTERN PetscErrorCode    PetscInfoSetClasses(PetscBool, PetscInt, const char *const *);
62 PETSC_EXTERN PetscErrorCode    PetscInfoGetClass(const char *, PetscBool *);
63 PETSC_EXTERN PetscErrorCode    PetscInfoGetInfo(PetscBool *, PetscBool *, PetscBool *, PetscBool *, PetscInfoCommFlag *);
64 PETSC_EXTERN PetscErrorCode    PetscInfoProcessClass(const char[], PetscInt, const PetscClassId[]);
65 PETSC_EXTERN PetscErrorCode    PetscInfoSetFilterCommSelf(PetscInfoCommFlag);
66 PETSC_EXTERN PetscErrorCode    PetscInfoSetFromOptions(PetscOptions);
67 PETSC_EXTERN PetscErrorCode    PetscInfoDestroy(void);
68 PETSC_EXTERN PetscBool         PetscLogPrintInfo; /* if true, indicates PetscInfo() is turned on */
69 
70 #define PETSC_EVENT 1311311
71 PETSC_EXTERN PetscLogEvent PETSC_LARGEST_EVENT;
72 
73 PETSC_EXTERN PetscErrorCode PetscIntStackCreate(PetscIntStack *);
74 PETSC_EXTERN PetscErrorCode PetscIntStackDestroy(PetscIntStack);
75 PETSC_EXTERN PetscErrorCode PetscIntStackPush(PetscIntStack, int);
76 PETSC_EXTERN PetscErrorCode PetscIntStackPop(PetscIntStack, int *);
77 PETSC_EXTERN PetscErrorCode PetscIntStackTop(PetscIntStack, int *);
78 PETSC_EXTERN PetscErrorCode PetscIntStackEmpty(PetscIntStack, PetscBool *);
79 
80 PETSC_EXTERN PetscErrorCode PetscLogStateCreate(PetscLogState *);
81 PETSC_EXTERN PetscErrorCode PetscLogStateDestroy(PetscLogState *);
82 PETSC_EXTERN PetscErrorCode PetscLogStateGetRegistry(PetscLogState, PetscLogRegistry *);
83 
84 PETSC_EXTERN PetscErrorCode PetscLogStateClassRegister(PetscLogState, const char[], PetscClassId, PetscLogStage *);
85 PETSC_EXTERN PetscErrorCode PetscLogStateClassSetActive(PetscLogState, PetscLogStage, PetscClassId, PetscBool);
86 PETSC_EXTERN PetscErrorCode PetscLogStateClassSetActiveAll(PetscLogState, PetscClassId, PetscBool);
87 
88 PETSC_EXTERN PetscErrorCode PetscLogStateStageRegister(PetscLogState, const char[], PetscLogStage *);
89 PETSC_EXTERN PetscErrorCode PetscLogStateStagePush(PetscLogState, PetscLogStage);
90 PETSC_EXTERN PetscErrorCode PetscLogStateStagePop(PetscLogState);
91 PETSC_EXTERN PetscErrorCode PetscLogStateStageSetActive(PetscLogState, PetscLogStage, PetscBool);
92 PETSC_EXTERN PetscErrorCode PetscLogStateStageGetActive(PetscLogState, PetscLogStage, PetscBool *);
93 PETSC_EXTERN PetscErrorCode PetscLogStateGetCurrentStage(PetscLogState, PetscLogStage *);
94 
95 PETSC_EXTERN PetscErrorCode PetscLogStateEventRegister(PetscLogState, const char[], PetscClassId, PetscLogEvent *);
96 PETSC_EXTERN PetscErrorCode PetscLogStateEventSetCollective(PetscLogState, PetscLogEvent, PetscBool);
97 PETSC_EXTERN PetscErrorCode PetscLogStateEventSetActive(PetscLogState, PetscLogStage, PetscLogEvent, PetscBool);
98 PETSC_EXTERN PetscErrorCode PetscLogStateEventSetActiveAll(PetscLogState, PetscLogEvent, PetscBool);
99 PETSC_EXTERN PetscErrorCode PetscLogStateEventGetActive(PetscLogState, PetscLogStage, PetscLogEvent, PetscBool *);
100 
101 PETSC_EXTERN PetscErrorCode PetscLogStateGetEventFromName(PetscLogState, const char[], PetscLogEvent *);
102 PETSC_EXTERN PetscErrorCode PetscLogStateGetStageFromName(PetscLogState, const char[], PetscLogStage *);
103 PETSC_EXTERN PetscErrorCode PetscLogStateGetClassFromName(PetscLogState, const char[], PetscLogClass *);
104 PETSC_EXTERN PetscErrorCode PetscLogStateGetClassFromClassId(PetscLogState, PetscClassId, PetscLogClass *);
105 PETSC_EXTERN PetscErrorCode PetscLogStateGetNumEvents(PetscLogState, PetscInt *);
106 PETSC_EXTERN PetscErrorCode PetscLogStateGetNumStages(PetscLogState, PetscInt *);
107 PETSC_EXTERN PetscErrorCode PetscLogStateGetNumClasses(PetscLogState, PetscInt *);
108 PETSC_EXTERN PetscErrorCode PetscLogStateEventGetInfo(PetscLogState, PetscLogEvent, PetscLogEventInfo *);
109 PETSC_EXTERN PetscErrorCode PetscLogStateStageGetInfo(PetscLogState, PetscLogStage, PetscLogStageInfo *);
110 PETSC_EXTERN PetscErrorCode PetscLogStateClassGetInfo(PetscLogState, PetscLogClass, PetscLogClassInfo *);
111 
112 PETSC_EXTERN PetscClassId PETSCLOGHANDLER_CLASSID;
113 
114 PETSC_EXTERN PetscFunctionList PetscLogHandlerList;
115 
116 PETSC_EXTERN PetscErrorCode PetscLogHandlerRegister(const char[], PetscErrorCode (*)(PetscLogHandler));
117 PETSC_EXTERN PetscErrorCode PetscLogHandlerCreate(MPI_Comm, PetscLogHandler *);
118 PETSC_EXTERN PetscErrorCode PetscLogHandlerSetType(PetscLogHandler, PetscLogHandlerType);
119 PETSC_EXTERN PetscErrorCode PetscLogHandlerGetType(PetscLogHandler, PetscLogHandlerType *);
120 PETSC_EXTERN PetscErrorCode PetscLogHandlerDestroy(PetscLogHandler *);
121 PETSC_EXTERN PetscErrorCode PetscLogHandlerSetState(PetscLogHandler, PetscLogState);
122 PETSC_EXTERN PetscErrorCode PetscLogHandlerGetState(PetscLogHandler, PetscLogState *);
123 PETSC_EXTERN PetscErrorCode PetscLogHandlerEventBegin(PetscLogHandler, PetscLogEvent, PetscObject, PetscObject, PetscObject, PetscObject);
124 PETSC_EXTERN PetscErrorCode PetscLogHandlerEventEnd(PetscLogHandler, PetscLogEvent, PetscObject, PetscObject, PetscObject, PetscObject);
125 PETSC_EXTERN PetscErrorCode PetscLogHandlerEventSync(PetscLogHandler, PetscLogEvent, MPI_Comm);
126 PETSC_EXTERN PetscErrorCode PetscLogHandlerObjectCreate(PetscLogHandler, PetscObject);
127 PETSC_EXTERN PetscErrorCode PetscLogHandlerObjectDestroy(PetscLogHandler, PetscObject);
128 PETSC_EXTERN PetscErrorCode PetscLogHandlerStagePush(PetscLogHandler, PetscLogStage);
129 PETSC_EXTERN PetscErrorCode PetscLogHandlerStagePop(PetscLogHandler, PetscLogStage);
130 PETSC_EXTERN PetscErrorCode PetscLogHandlerView(PetscLogHandler, PetscViewer);
131 
132 PETSC_EXTERN PetscErrorCode PetscLogHandlerCreateTrace(MPI_Comm, FILE *, PetscLogHandler *);
133 
134 /* All events are inactive if an invalid stage is set, like if there have been more stage pops than stage pushes */
135 #define PetscLogStateStageEventIsActive(state, stage, event) ((stage >= 0) && PetscBTLookup((state)->active, (stage)) && PetscBTLookup((state)->active, (stage) + (event + 1) * (state)->bt_num_stages))
136 
137 /* PetscLogHandler with critical methods exposed for speed */
138 typedef struct _n_PetscLogHandlerHot {
139   PetscLogHandler handler;
140   PetscErrorCode (*eventBegin)(PetscLogHandler, PetscLogEvent, PetscObject, PetscObject, PetscObject, PetscObject);
141   PetscErrorCode (*eventEnd)(PetscLogHandler, PetscLogEvent, PetscObject, PetscObject, PetscObject, PetscObject);
142   PetscErrorCode (*eventSync)(PetscLogHandler, PetscLogEvent, MPI_Comm);
143   PetscErrorCode (*objectCreate)(PetscLogHandler, PetscObject);
144   PetscErrorCode (*objectDestroy)(PetscLogHandler, PetscObject);
145 } PetscLogHandlerHot;
146 
147 /* Handle multithreading */
148 #if defined(PETSC_HAVE_THREADSAFETY)
149   #if defined(__cplusplus)
150     #define PETSC_TLS thread_local
151   #else
152     #define PETSC_TLS _Thread_local
153   #endif
154   #define PETSC_EXTERN_TLS extern PETSC_TLS PETSC_VISIBILITY_PUBLIC
155 PETSC_EXTERN PetscErrorCode PetscAddLogDouble(PetscLogDouble *, PetscLogDouble *, PetscLogDouble);
156 PETSC_EXTERN PetscErrorCode PetscAddLogDoubleCnt(PetscLogDouble *, PetscLogDouble *, PetscLogDouble *, PetscLogDouble *, PetscLogDouble);
157 #else
158   #define PETSC_EXTERN_TLS PETSC_EXTERN
159   #define PETSC_TLS
160   #define PetscAddLogDouble(a, b, c)          ((PetscErrorCode)((*(a) += (c), PETSC_SUCCESS) || ((*(b) += (c)), PETSC_SUCCESS)))
161   #define PetscAddLogDoubleCnt(a, b, c, d, e) ((PetscErrorCode)(PetscAddLogDouble(a, c, 1) || PetscAddLogDouble(b, d, e)))
162 #endif
163 
164 /*
165     PetscClassRegInfo, PetscClassPerfInfo - Each class has two data structures associated with it. The first has
166        static information about it, the second collects statistics on how many objects of the class are created,
167        how much memory they use, etc.
168 
169     PetscClassRegLog, PetscClassPerfLog - arrays of the PetscClassRegInfo and PetscClassPerfInfo for all classes.
170 */
171 typedef struct {
172   char        *name;    /* The class name */
173   PetscClassId classid; /* The integer identifying this class */
174 } PetscClassRegInfo;
175 
176 typedef struct {
177   PetscClassId   id;           /* The integer identifying this class */
178   int            creations;    /* The number of objects of this class created */
179   int            destructions; /* The number of objects of this class destroyed */
180   PetscLogDouble mem;          /* The total memory allocated by objects of this class; this is completely wrong and should possibly be removed */
181   PetscLogDouble descMem;      /* The total memory allocated by descendents of these objects; this is completely wrong and should possibly be removed */
182 } PetscClassPerfInfo;
183 
184 typedef struct _n_PetscClassRegLog *PetscClassRegLog;
185 struct _n_PetscClassRegLog {
186   int                numClasses; /* The number of classes registered */
187   int                maxClasses; /* The maximum number of classes */
188   PetscClassRegInfo *classInfo;  /* The structure for class information (classids are monotonicly increasing) */
189 };
190 
191 typedef struct _n_PetscClassPerfLog *PetscClassPerfLog;
192 struct _n_PetscClassPerfLog {
193   int                 numClasses; /* The number of logging classes */
194   int                 maxClasses; /* The maximum number of classes */
195   PetscClassPerfInfo *classInfo;  /* The structure for class information (classids are monotonicly increasing) */
196 };
197 
198 /*
199     PetscEventRegInfo, PetscEventPerfInfo - Each event has two data structures associated with it. The first has
200        static information about it, the second collects statistics on how many times the event is used, how
201        much time it takes, etc.
202 
203     PetscEventRegLog, PetscEventPerfLog - an array of all PetscEventRegInfo and PetscEventPerfInfo for all events. There is one
204       of these for each stage.
205 
206 */
207 typedef struct {
208   char        *name;       /* The name of this event */
209   PetscClassId classid;    /* The class the event is associated with */
210   PetscBool    collective; /* Flag this event as collective */
211 #if defined(PETSC_HAVE_TAU_PERFSTUBS)
212   void *timer; /* Associated external tool timer for this event */
213 #endif
214 #if defined(PETSC_HAVE_MPE)
215   int mpe_id_begin; /* MPE IDs that define the event */
216   int mpe_id_end;
217 #endif
218 } PetscEventRegInfo;
219 
220 typedef struct _n_PetscEventRegLog *PetscEventRegLog;
221 struct _n_PetscEventRegLog {
222   int                numEvents; /* The number of registered events */
223   int                maxEvents; /* The maximum number of events */
224   PetscEventRegInfo *eventInfo; /* The registration information for each event */
225 };
226 
227 typedef struct _n_PetscEventPerfLog *PetscEventPerfLog;
228 struct _n_PetscEventPerfLog {
229   int                 numEvents; /* The number of logging events */
230   int                 maxEvents; /* The maximum number of events */
231   PetscEventPerfInfo *eventInfo; /* The performance information for each event */
232 };
233 
234 /*
235    PetscStageInfo - Contains all the information about a particular stage.
236 
237    PetscStageLog - An array of PetscStageInfo for each registered stage. There is a single one of these in the code.
238 */
239 typedef struct _PetscStageInfo {
240   char              *name;     /* The stage name */
241   PetscBool          used;     /* The stage was pushed on this processor */
242   PetscEventPerfInfo perfInfo; /* The stage performance information */
243   PetscEventPerfLog  eventLog; /* The event information for this stage */
244   PetscClassPerfLog  classLog; /* The class information for this stage */
245 #if defined(PETSC_HAVE_TAU_PERFSTUBS)
246   void *timer; /* Associated external tool timer for this stage */
247 #endif
248 } PetscStageInfo;
249 
250 typedef struct _n_PetscStageLog *PetscStageLog;
251 struct _n_PetscStageLog {
252   int              numStages; /* The number of registered stages */
253   int              maxStages; /* The maximum number of stages */
254   PetscIntStack    stack;     /* The stack for active stages */
255   int              curStage;  /* The current stage (only used in macros so we don't call PetscIntStackTop) */
256   PetscStageInfo  *stageInfo; /* The information for each stage */
257   PetscEventRegLog eventLog;  /* The registered events */
258   PetscClassRegLog classLog;  /* The registered classes */
259 };
260 
261 PETSC_DEPRECATED_FUNCTION(3, 18, 0, "PetscLogObjectParent()", ) static inline PetscErrorCode PetscLogObjectParent(PetscObject o, PetscObject p)
262 {
263   (void)o;
264   (void)p;
265   return PETSC_SUCCESS;
266 }
267 #define PetscLogObjectParents(p, n, d) PetscMacroReturnStandard(for (int _i = 0; _i < (n); ++_i) PetscCall(PetscLogObjectParent((PetscObject)(p), (PetscObject)(d)[_i]));)
268 
269 PETSC_DEPRECATED_FUNCTION(3, 18, 0, "PetscLogObjectMemory()", ) static inline PetscErrorCode PetscLogObjectMemory(PetscObject o, PetscLogDouble m)
270 {
271   (void)o;
272   (void)m;
273   return PETSC_SUCCESS;
274 }
275 
276 /* Global flop counter */
277 PETSC_EXTERN PetscLogDouble petsc_TotalFlops;
278 PETSC_EXTERN PetscLogDouble petsc_irecv_ct;
279 PETSC_EXTERN PetscLogDouble petsc_isend_ct;
280 PETSC_EXTERN PetscLogDouble petsc_recv_ct;
281 PETSC_EXTERN PetscLogDouble petsc_send_ct;
282 PETSC_EXTERN PetscLogDouble petsc_irecv_len;
283 PETSC_EXTERN PetscLogDouble petsc_isend_len;
284 PETSC_EXTERN PetscLogDouble petsc_recv_len;
285 PETSC_EXTERN PetscLogDouble petsc_send_len;
286 PETSC_EXTERN PetscLogDouble petsc_allreduce_ct;
287 PETSC_EXTERN PetscLogDouble petsc_gather_ct;
288 PETSC_EXTERN PetscLogDouble petsc_scatter_ct;
289 PETSC_EXTERN PetscLogDouble petsc_wait_ct;
290 PETSC_EXTERN PetscLogDouble petsc_wait_any_ct;
291 PETSC_EXTERN PetscLogDouble petsc_wait_all_ct;
292 PETSC_EXTERN PetscLogDouble petsc_sum_of_waits_ct;
293 
294 /* Thread local storage */
295 PETSC_EXTERN_TLS PetscLogDouble petsc_TotalFlops_th;
296 PETSC_EXTERN_TLS PetscLogDouble petsc_irecv_ct_th;
297 PETSC_EXTERN_TLS PetscLogDouble petsc_isend_ct_th;
298 PETSC_EXTERN_TLS PetscLogDouble petsc_recv_ct_th;
299 PETSC_EXTERN_TLS PetscLogDouble petsc_send_ct_th;
300 PETSC_EXTERN_TLS PetscLogDouble petsc_irecv_len_th;
301 PETSC_EXTERN_TLS PetscLogDouble petsc_isend_len_th;
302 PETSC_EXTERN_TLS PetscLogDouble petsc_recv_len_th;
303 PETSC_EXTERN_TLS PetscLogDouble petsc_send_len_th;
304 PETSC_EXTERN_TLS PetscLogDouble petsc_allreduce_ct_th;
305 PETSC_EXTERN_TLS PetscLogDouble petsc_gather_ct_th;
306 PETSC_EXTERN_TLS PetscLogDouble petsc_scatter_ct_th;
307 PETSC_EXTERN_TLS PetscLogDouble petsc_wait_ct_th;
308 PETSC_EXTERN_TLS PetscLogDouble petsc_wait_any_ct_th;
309 PETSC_EXTERN_TLS PetscLogDouble petsc_wait_all_ct_th;
310 PETSC_EXTERN_TLS PetscLogDouble petsc_sum_of_waits_ct_th;
311 
312 /* Global GPU counters */
313 PETSC_EXTERN PetscLogDouble petsc_ctog_ct;
314 PETSC_EXTERN PetscLogDouble petsc_gtoc_ct;
315 PETSC_EXTERN PetscLogDouble petsc_ctog_sz;
316 PETSC_EXTERN PetscLogDouble petsc_gtoc_sz;
317 PETSC_EXTERN PetscLogDouble petsc_ctog_ct_scalar;
318 PETSC_EXTERN PetscLogDouble petsc_gtoc_ct_scalar;
319 PETSC_EXTERN PetscLogDouble petsc_ctog_sz_scalar;
320 PETSC_EXTERN PetscLogDouble petsc_gtoc_sz_scalar;
321 PETSC_EXTERN PetscLogDouble petsc_gflops;
322 PETSC_EXTERN PetscLogDouble petsc_gtime;
323 
324 /* Thread local storage */
325 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_ct_th;
326 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_ct_th;
327 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_sz_th;
328 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_sz_th;
329 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_ct_scalar_th;
330 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_ct_scalar_th;
331 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_sz_scalar_th;
332 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_sz_scalar_th;
333 PETSC_EXTERN_TLS PetscLogDouble petsc_gflops_th;
334 PETSC_EXTERN_TLS PetscLogDouble petsc_gtime_th;
335 
336 PETSC_EXTERN PetscBool PetscLogMemory;
337 PETSC_EXTERN PetscBool PetscLogSyncOn; /* true if logging synchronization is enabled */
338 
339 PETSC_EXTERN PetscLogState petsc_log_state;
340 
341 #define PETSC_LOG_HANDLER_MAX 4
342 PETSC_EXTERN PetscLogHandlerHot PetscLogHandlers[PETSC_LOG_HANDLER_MAX];
343 
344 #if defined(PETSC_USE_LOG) /* --- Logging is turned on --------------------------------*/
345 PETSC_EXTERN PetscStageLog  petsc_stageLog;
346 PETSC_EXTERN PetscErrorCode PetscLogGetStageLog(PetscStageLog *);
347 PETSC_EXTERN PetscErrorCode PetscStageLogGetCurrent(PetscStageLog, int *);
348 PETSC_EXTERN PetscErrorCode PetscStageLogGetEventPerfLog(PetscStageLog, int, PetscEventPerfLog *);
349 
350 PETSC_EXTERN PetscErrorCode PetscGetFlops(PetscLogDouble *);
351 
352 PETSC_EXTERN PetscErrorCode (*PetscLogPLB)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject);
353 PETSC_EXTERN PetscErrorCode (*PetscLogPLE)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject);
354 PETSC_EXTERN PetscErrorCode (*PetscLogPHC)(PetscObject);
355 PETSC_EXTERN PetscErrorCode (*PetscLogPHD)(PetscObject);
356 
357   #define PetscLogObjectCreate(h)  ((PetscLogPHC) ? (*PetscLogPHC)((PetscObject)(h)) : PETSC_SUCCESS)
358   #define PetscLogObjectDestroy(h) ((PetscLogPHD) ? (*PetscLogPHD)((PetscObject)(h)) : PETSC_SUCCESS)
359 PETSC_EXTERN PetscErrorCode PetscLogObjectState(PetscObject, const char[], ...) PETSC_ATTRIBUTE_FORMAT(2, 3);
360 
361 /* Initialization functions */
362 PETSC_EXTERN PetscErrorCode PetscLogDefaultBegin(void);
363 PETSC_EXTERN PetscErrorCode PetscLogAllBegin(void);
364 PETSC_EXTERN PetscErrorCode PetscLogNestedBegin(void);
365 PETSC_EXTERN PetscErrorCode PetscLogTraceBegin(FILE *);
366 PETSC_EXTERN PetscErrorCode PetscLogMPEBegin(void);
367 PETSC_EXTERN PetscErrorCode PetscLogPerfstubsBegin(void);
368 PETSC_EXTERN PetscErrorCode PetscLogLegacyCallbacksBegin(PetscErrorCode (*)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject), PetscErrorCode (*)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject), PetscErrorCode (*)(PetscObject), PetscErrorCode (*)(PetscObject));
369 PETSC_EXTERN PetscErrorCode PetscLogActions(PetscBool);
370 PETSC_EXTERN PetscErrorCode PetscLogObjects(PetscBool);
371 PETSC_EXTERN PetscErrorCode PetscLogSetThreshold(PetscLogDouble, PetscLogDouble *);
372 PETSC_EXTERN PetscErrorCode PetscLogSet(PetscErrorCode (*)(int, int, PetscObject, PetscObject, PetscObject, PetscObject), PetscErrorCode (*)(int, int, PetscObject, PetscObject, PetscObject, PetscObject));
373 
374 /* Output functions */
375 PETSC_EXTERN PetscErrorCode PetscLogView(PetscViewer);
376 PETSC_EXTERN PetscErrorCode PetscLogViewFromOptions(void);
377 PETSC_EXTERN PetscErrorCode PetscLogDump(const char[]);
378 PETSC_EXTERN PetscErrorCode PetscLogMPEDump(const char[]);
379 
380 PETSC_EXTERN PetscErrorCode PetscLogGetState(PetscLogState *);
381 PETSC_EXTERN PetscErrorCode PetscLogHandlerStart(PetscLogHandler);
382 PETSC_EXTERN PetscErrorCode PetscLogHandlerStop(PetscLogHandler);
383 
384 /* Status checking functions */
385 PETSC_EXTERN PetscErrorCode PetscLogIsActive(PetscBool *);
386 
387 /* Stage functions */
388 PETSC_EXTERN PetscErrorCode PetscLogStageRegister(const char[], PetscLogStage *);
389 PETSC_EXTERN PetscErrorCode PetscLogStagePush(PetscLogStage);
390 PETSC_EXTERN PetscErrorCode PetscLogStagePop(void);
391 PETSC_EXTERN PetscErrorCode PetscLogStageSetActive(PetscLogStage, PetscBool);
392 PETSC_EXTERN PetscErrorCode PetscLogStageGetActive(PetscLogStage, PetscBool *);
393 PETSC_EXTERN PetscErrorCode PetscLogStageSetVisible(PetscLogStage, PetscBool);
394 PETSC_EXTERN PetscErrorCode PetscLogStageGetVisible(PetscLogStage, PetscBool *);
395 PETSC_EXTERN PetscErrorCode PetscLogStageGetId(const char[], PetscLogStage *);
396 PETSC_EXTERN PetscErrorCode PetscLogStageGetName(PetscLogEvent, const char **);
397 
398 /* Event functions */
399 PETSC_EXTERN PetscErrorCode PetscLogEventRegister(const char[], PetscClassId, PetscLogEvent *);
400 PETSC_EXTERN PetscErrorCode PetscLogEventSetCollective(PetscLogEvent, PetscBool);
401 PETSC_EXTERN PetscErrorCode PetscLogEventIncludeClass(PetscClassId);
402 PETSC_EXTERN PetscErrorCode PetscLogEventExcludeClass(PetscClassId);
403 PETSC_EXTERN PetscErrorCode PetscLogEventActivate(PetscLogEvent);
404 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivate(PetscLogEvent);
405 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivatePush(PetscLogEvent);
406 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivatePop(PetscLogEvent);
407 PETSC_EXTERN PetscErrorCode PetscLogEventSetActiveAll(PetscLogEvent, PetscBool);
408 PETSC_EXTERN PetscErrorCode PetscLogEventActivateClass(PetscClassId);
409 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivateClass(PetscClassId);
410 PETSC_EXTERN PetscErrorCode PetscLogEventGetId(const char[], PetscLogEvent *);
411 PETSC_EXTERN PetscErrorCode PetscLogEventGetName(PetscLogEvent, const char **);
412 PETSC_EXTERN PetscErrorCode PetscLogEventGetPerfInfo(PetscLogStage, PetscLogEvent, PetscEventPerfInfo *);
413 PETSC_EXTERN PetscErrorCode PetscLogEventSetDof(PetscLogEvent, PetscInt, PetscLogDouble);
414 PETSC_EXTERN PetscErrorCode PetscLogEventSetError(PetscLogEvent, PetscInt, PetscLogDouble);
415 PETSC_EXTERN PetscErrorCode PetscLogPushCurrentEvent_Internal(PetscLogEvent);
416 PETSC_EXTERN PetscErrorCode PetscLogPopCurrentEvent_Internal(void);
417 PETSC_EXTERN PetscErrorCode PetscLogEventsPause(void);
418 PETSC_EXTERN PetscErrorCode PetscLogEventsResume(void);
419 
420 /* Class functions */
421 PETSC_EXTERN PetscErrorCode PetscLogClassGetClassId(const char[], PetscClassId *);
422 PETSC_EXTERN PetscErrorCode PetscLogClassIdGetName(PetscClassId, const char **);
423 
424 PETSC_EXTERN PetscErrorCode PetscLogEventSynchronize(PetscLogEvent, MPI_Comm);
425 
426   #define PetscLogEventSync(e, comm) \
427     ((PetscErrorCode)(((PetscLogPLB && petsc_stageLog->stageInfo[petsc_stageLog->curStage].perfInfo.active && petsc_stageLog->stageInfo[petsc_stageLog->curStage].eventLog->eventInfo[e].active) ? PetscLogEventSynchronize((e), (comm)) : PETSC_SUCCESS)))
428 
429   #define PetscLogEventBegin(e, o1, o2, o3, o4) \
430     ((PetscErrorCode)((PetscLogPLB && petsc_stageLog->stageInfo[petsc_stageLog->curStage].perfInfo.active && petsc_stageLog->stageInfo[petsc_stageLog->curStage].eventLog->eventInfo[e].active) ? (PetscErrorCode)(((*PetscLogPLB)((e), 0, (PetscObject)(o1), (PetscObject)(o2), (PetscObject)(o3), (PetscObject)(o4))) || PetscLogPushCurrentEvent_Internal(e)) : PETSC_SUCCESS))
431 
432   #define PetscLogEventEnd(e, o1, o2, o3, o4) \
433     ((PetscErrorCode)((PetscLogPLE && petsc_stageLog->stageInfo[petsc_stageLog->curStage].perfInfo.active && petsc_stageLog->stageInfo[petsc_stageLog->curStage].eventLog->eventInfo[e].active) ? (PetscErrorCode)(((*PetscLogPLE)((e), 0, (PetscObject)(o1), (PetscObject)(o2), (PetscObject)(o3), (PetscObject)(o4))) || PetscLogPopCurrentEvent_Internal()) : PETSC_SUCCESS))
434 
435 PETSC_EXTERN PetscErrorCode PetscLogEventGetFlops(PetscLogEvent, PetscLogDouble *);
436 PETSC_EXTERN PetscErrorCode PetscLogEventZeroFlops(PetscLogEvent);
437 
438   /*
439    Flop counting:  We count each arithmetic operation (e.g., addition, multiplication) separately.
440 
441    For the complex numbers version, note that
442        1 complex addition = 2 flops
443        1 complex multiplication = 6 flops,
444    where we define 1 flop as that for a double precision scalar.  We roughly approximate
445    flop counting for complex numbers by multiplying the total flops by 4; this corresponds
446    to the assumption that we're counting mostly additions and multiplications -- and
447    roughly the same number of each.  More accurate counting could be done by distinguishing
448    among the various arithmetic operations.
449  */
450 
451   #if defined(PETSC_USE_COMPLEX)
452     #define PETSC_FLOPS_PER_OP 4.0
453   #else
454     #define PETSC_FLOPS_PER_OP 1.0
455   #endif
456 
457 /*@C
458        PetscLogFlops - Log how many flops are performed in a calculation
459 
460    Input Parameter:
461 .   flops - the number of flops
462 
463    Level: intermediate
464 
465    Note:
466      To limit the chance of integer overflow when multiplying by a constant, represent the constant as a double,
467      not an integer. Use `PetscLogFlops`(4.0*n) not `PetscLogFlops`(4*n)
468 
469 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`
470 @*/
471 static inline PetscErrorCode PetscLogFlops(PetscLogDouble n)
472 {
473   PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot log negative flops");
474   return PetscAddLogDouble(&petsc_TotalFlops, &petsc_TotalFlops_th, PETSC_FLOPS_PER_OP * n);
475 }
476 
477   /*
478      These are used internally in the PETSc routines to keep a count of MPI messages and
479    their sizes.
480 
481      This does not work for MPI-Uni because our include/petsc/mpiuni/mpi.h file
482    uses macros to defined the MPI operations.
483 
484      It does not work correctly from HP-UX because it processes the
485    macros in a way that sometimes it double counts, hence
486    PETSC_HAVE_BROKEN_RECURSIVE_MACRO
487 
488      It does not work with Windows because winmpich lacks MPI_Type_size()
489 */
490   #if !defined(MPIUNI_H) && !defined(PETSC_HAVE_BROKEN_RECURSIVE_MACRO)
491 /*
492    Logging of MPI activities
493 */
494 static inline PetscErrorCode PetscMPITypeSize(PetscInt count, MPI_Datatype type, PetscLogDouble *length, PetscLogDouble *length_th)
495 {
496   PetscMPIInt typesize;
497 
498   if (type == MPI_DATATYPE_NULL) return PETSC_SUCCESS;
499   PetscCallMPI(MPI_Type_size(type, &typesize));
500   return PetscAddLogDouble(length, length_th, (PetscLogDouble)(count * typesize));
501 }
502 
503 static inline PetscErrorCode PetscMPITypeSizeComm(MPI_Comm comm, const PetscMPIInt *counts, MPI_Datatype type, PetscLogDouble *length, PetscLogDouble *length_th)
504 {
505   PetscMPIInt    typesize, size, p;
506   PetscLogDouble l;
507 
508   if (type == MPI_DATATYPE_NULL) return PETSC_SUCCESS;
509   PetscCallMPI(MPI_Comm_size(comm, &size));
510   PetscCallMPI(MPI_Type_size(type, &typesize));
511   for (p = 0, l = 0.0; p < size; ++p) l += (PetscLogDouble)(counts[p] * typesize);
512   return PetscAddLogDouble(length, length_th, l);
513 }
514 
515 /*
516     Returns 1 if the communicator is parallel else zero
517 */
518 static inline int PetscMPIParallelComm(MPI_Comm comm)
519 {
520   PetscMPIInt size;
521   MPI_Comm_size(comm, &size);
522   return size > 1;
523 }
524 
525     #define MPI_Irecv(buf, count, datatype, source, tag, comm, request) \
526       (PetscAddLogDouble(&petsc_irecv_ct, &petsc_irecv_ct_th, 1) || PetscMPITypeSize((count), (datatype), &(petsc_irecv_len), &(petsc_irecv_len_th)) || MPI_Irecv((buf), (count), (datatype), (source), (tag), (comm), (request)))
527 
528     #define MPI_Irecv_c(buf, count, datatype, source, tag, comm, request) \
529       (PetscAddLogDouble(&petsc_irecv_ct, &petsc_irecv_ct_th, 1) || PetscMPITypeSize((count), (datatype), &(petsc_irecv_len), &(petsc_irecv_len_th)) || MPI_Irecv_c((buf), (count), (datatype), (source), (tag), (comm), (request)))
530 
531     #define MPI_Isend(buf, count, datatype, dest, tag, comm, request) \
532       (PetscAddLogDouble(&petsc_isend_ct, &petsc_isend_ct_th, 1) || PetscMPITypeSize((count), (datatype), &(petsc_isend_len), &(petsc_isend_len_th)) || MPI_Isend((buf), (count), (datatype), (dest), (tag), (comm), (request)))
533 
534     #define MPI_Isend_c(buf, count, datatype, dest, tag, comm, request) \
535       (PetscAddLogDouble(&petsc_isend_ct, &petsc_isend_ct_th, 1) || PetscMPITypeSize((count), (datatype), &(petsc_isend_len), &(petsc_isend_len_th)) || MPI_Isend_c((buf), (count), (datatype), (dest), (tag), (comm), (request)))
536 
537     #define MPI_Startall_irecv(count, datatype, number, requests) \
538       (PetscAddLogDouble(&petsc_irecv_ct, &petsc_irecv_ct_th, number) || PetscMPITypeSize((count), (datatype), &(petsc_irecv_len), &(petsc_irecv_len_th)) || ((number) && MPI_Startall((number), (requests))))
539 
540     #define MPI_Startall_isend(count, datatype, number, requests) \
541       (PetscAddLogDouble(&petsc_isend_ct, &petsc_isend_ct_th, number) || PetscMPITypeSize((count), (datatype), &(petsc_isend_len), &(petsc_isend_len_th)) || ((number) && MPI_Startall((number), (requests))))
542 
543     #define MPI_Start_isend(count, datatype, requests) (PetscAddLogDouble(&petsc_isend_ct, &petsc_isend_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_isend_len), (&petsc_isend_len_th)) || MPI_Start((requests)))
544 
545     #define MPI_Recv(buf, count, datatype, source, tag, comm, status) \
546       (PetscAddLogDouble(&petsc_recv_ct, &petsc_recv_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_recv_len), (&petsc_recv_len_th)) || MPI_Recv((buf), (count), (datatype), (source), (tag), (comm), (status)))
547 
548     #define MPI_Recv_c(buf, count, datatype, source, tag, comm, status) \
549       (PetscAddLogDouble(&petsc_recv_ct, &petsc_recv_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_recv_len), &(petsc_recv_len_th)) || MPI_Recv_c((buf), (count), (datatype), (source), (tag), (comm), (status)))
550 
551     #define MPI_Send(buf, count, datatype, dest, tag, comm) \
552       (PetscAddLogDouble(&petsc_send_ct, &petsc_send_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Send((buf), (count), (datatype), (dest), (tag), (comm)))
553 
554     #define MPI_Send_c(buf, count, datatype, dest, tag, comm) \
555       (PetscAddLogDouble(&petsc_send_ct, &petsc_send_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Send_c((buf), (count), (datatype), (dest), (tag), (comm)))
556 
557     #define MPI_Wait(request, status) (PetscAddLogDouble(&petsc_wait_ct, &petsc_wait_ct_th, 1) || PetscAddLogDouble(&petsc_sum_of_waits_ct, &petsc_sum_of_waits_ct_th, 1) || MPI_Wait((request), (status)))
558 
559     #define MPI_Waitany(a, b, c, d) (PetscAddLogDouble(&petsc_wait_any_ct, &petsc_wait_any_ct_th, 1) || PetscAddLogDouble(&petsc_sum_of_waits_ct, &petsc_sum_of_waits_ct_th, 1) || MPI_Waitany((a), (b), (c), (d)))
560 
561     #define MPI_Waitall(count, array_of_requests, array_of_statuses) \
562       (PetscAddLogDouble(&petsc_wait_all_ct, &petsc_wait_all_ct_th, 1) || PetscAddLogDouble(&petsc_sum_of_waits_ct, &petsc_sum_of_waits_ct_th, count) || MPI_Waitall((count), (array_of_requests), (array_of_statuses)))
563 
564     #define MPI_Allreduce(sendbuf, recvbuf, count, datatype, op, comm) (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || MPI_Allreduce((sendbuf), (recvbuf), (count), (datatype), (op), (comm)))
565 
566     #define MPI_Bcast(buffer, count, datatype, root, comm) (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || MPI_Bcast((buffer), (count), (datatype), (root), (comm)))
567 
568     #define MPI_Reduce_scatter_block(sendbuf, recvbuf, recvcount, datatype, op, comm) \
569       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || MPI_Reduce_scatter_block((sendbuf), (recvbuf), (recvcount), (datatype), (op), (comm)))
570 
571     #define MPI_Alltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm) \
572       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || PetscMPITypeSize((sendcount), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Alltoall((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (comm)))
573 
574     #define MPI_Alltoallv(sendbuf, sendcnts, sdispls, sendtype, recvbuf, recvcnts, rdispls, recvtype, comm) \
575       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || PetscMPITypeSizeComm((comm), (sendcnts), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Alltoallv((sendbuf), (sendcnts), (sdispls), (sendtype), (recvbuf), (recvcnts), (rdispls), (recvtype), (comm)))
576 
577     #define MPI_Allgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm) \
578       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Allgather((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (comm)))
579 
580     #define MPI_Allgatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, comm) \
581       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Allgatherv((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (displs), (recvtype), (comm)))
582 
583     #define MPI_Gather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm) \
584       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, 1) || PetscMPITypeSize((sendcount), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Gather((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (root), (comm)))
585 
586     #define MPI_Gatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, root, comm) \
587       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, 1) || PetscMPITypeSize((sendcount), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Gatherv((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (displs), (recvtype), (root), (comm)))
588 
589     #define MPI_Scatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm) \
590       (PetscAddLogDouble(&petsc_scatter_ct, &petsc_scatter_ct_th, 1) || PetscMPITypeSize((recvcount), (recvtype), (&petsc_recv_len), &(petsc_recv_len_th)) || MPI_Scatter((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (root), (comm)))
591 
592     #define MPI_Scatterv(sendbuf, sendcount, displs, sendtype, recvbuf, recvcount, recvtype, root, comm) \
593       (PetscAddLogDouble(&petsc_scatter_ct, &petsc_scatter_ct_th, 1) || PetscMPITypeSize((recvcount), (recvtype), (&petsc_recv_len), &(petsc_recv_len_th)) || MPI_Scatterv((sendbuf), (sendcount), (displs), (sendtype), (recvbuf), (recvcount), (recvtype), (root), (comm)))
594 
595     #define MPI_Ialltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm, request) \
596       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || PetscMPITypeSize((sendcount), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Ialltoall((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (comm), (request)))
597 
598     #define MPI_Ialltoallv(sendbuf, sendcnts, sdispls, sendtype, recvbuf, recvcnts, rdispls, recvtype, comm, request) \
599       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || PetscMPITypeSizeComm((comm), (sendcnts), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Ialltoallv((sendbuf), (sendcnts), (sdispls), (sendtype), (recvbuf), (recvcnts), (rdispls), (recvtype), (comm), (request)))
600 
601     #define MPI_Iallgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm, request) \
602       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Iallgather((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (comm), (request)))
603 
604     #define MPI_Iallgatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, comm, request) \
605       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Iallgatherv((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (displs), (recvtype), (comm), (request)))
606 
607     #define MPI_Igather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm, request) \
608       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, 1) || PetscMPITypeSize((sendcount), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Igather((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (root), (comm), (request)))
609 
610     #define MPI_Igatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, root, comm, request) \
611       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, 1) || PetscMPITypeSize((sendcount), (sendtype), (&petsc_send_len), (&petsc_send_len_th)) || MPI_Igatherv((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (displs), (recvtype), (root), (comm), (request)))
612 
613     #define MPI_Iscatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm, request) \
614       (PetscAddLogDouble(&petsc_scatter_ct, &petsc_scatter_ct_th, 1) || PetscMPITypeSize((recvcount), (recvtype), (&petsc_recv_len), (&petsc_recv_len_th)) || MPI_Iscatter((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (root), (comm), (request)))
615 
616     #define MPI_Iscatterv(sendbuf, sendcount, displs, sendtype, recvbuf, recvcount, recvtype, root, comm, request) \
617       (PetscAddLogDouble(&petsc_scatter_ct, &petsc_scatter_ct_th, 1) || PetscMPITypeSize((recvcount), (recvtype), (&petsc_recv_len), (&petsc_recv_len_th)) || MPI_Iscatterv((sendbuf), (sendcount), (displs), (sendtype), (recvbuf), (recvcount), (recvtype), (root), (comm), (request)))
618 
619     #define MPIX_Send_enqueue(buf, count, datatype, dest, tag, comm) \
620       (PetscAddLogDouble(&petsc_send_ct, &petsc_send_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_send_len), (&petsc_send_len_th)) || MPIX_Send_enqueue((buf), (count), (datatype), (dest), (tag), (comm)))
621 
622     #define MPIX_Recv_enqueue(buf, count, datatype, source, tag, comm, status) \
623       (PetscAddLogDouble(&petsc_recv_ct, &petsc_recv_ct_th, 1) || PetscMPITypeSize((count), (datatype), (&petsc_recv_len), (&petsc_recv_len_th)) || MPIX_Recv_enqueue((buf), (count), (datatype), (source), (tag), (comm), (status)))
624 
625     #define MPIX_Isend_enqueue(buf, count, datatype, dest, tag, comm, request) \
626       (PetscAddLogDouble(&petsc_isend_ct, &petsc_isend_ct_th, 1) || PetscMPITypeSize((count), (datatype), &(petsc_isend_len), &(petsc_isend_len_th)) || MPIX_Isend_enqueue((buf), (count), (datatype), (dest), (tag), (comm), (request)))
627 
628     #define MPIX_Irecv_enqueue(buf, count, datatype, source, tag, comm, request) \
629       (PetscAddLogDouble(&petsc_irecv_ct, &petsc_irecv_ct_th, 1) || PetscMPITypeSize((count), (datatype), &(petsc_irecv_len), &(petsc_irecv_len_th)) || MPIX_Irecv_enqueue((buf), (count), (datatype), (source), (tag), (comm), (request)))
630 
631     #define MPIX_Allreduce_enqueue(sendbuf, recvbuf, count, datatype, op, comm) \
632       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || MPIX_Allreduce_enqueue((sendbuf), (recvbuf), (count), (datatype), (op), (comm)))
633 
634     #define MPIX_Wait_enqueue(request, status) (PetscAddLogDouble(&petsc_wait_ct, &petsc_wait_ct_th, 1) || PetscAddLogDouble(&petsc_sum_of_waits_ct, &petsc_sum_of_waits_ct_th, 1) || MPIX_Wait_enqueue((request), (status)))
635 
636     #define MPIX_Waitall_enqueue(count, array_of_requests, array_of_statuses) \
637       (PetscAddLogDouble(&petsc_wait_all_ct, &petsc_wait_all_ct_th, 1) || PetscAddLogDouble(&petsc_sum_of_waits_ct, &petsc_sum_of_waits_ct_th, count) || MPIX_Waitall_enqueue((count), (array_of_requests), (array_of_statuses)))
638   #else
639 
640     #define MPI_Startall_irecv(count, datatype, number, requests) ((number) && MPI_Startall((number), (requests)))
641 
642     #define MPI_Startall_isend(count, datatype, number, requests) ((number) && MPI_Startall((number), (requests)))
643 
644     #define MPI_Start_isend(count, datatype, requests) (MPI_Start((requests)))
645 
646   #endif /* !MPIUNI_H && ! PETSC_HAVE_BROKEN_RECURSIVE_MACRO */
647 
648 #else /* ---Logging is turned off --------------------------------------------*/
649 
650   #define PetscLogGetState(a)     (*(a) = NULL, PETSC_SUCCESS)
651   #define PetscLogHandlerStart(a) ((void)(a), PETSC_SUCCESS)
652   #define PetscLogHandlerStop(a)  ((void)(a), PETSC_SUCCESS)
653 
654   #define PetscLogFlops(n) ((void)(n), PETSC_SUCCESS)
655   #define PetscGetFlops(a) (*(a) = 0.0, PETSC_SUCCESS)
656 
657   #define PetscLogStageRegister(a, b)   ((void)(a), *(b) = -1, PETSC_SUCCESS)
658   #define PetscLogStagePush(a)          ((void)(a), PETSC_SUCCESS)
659   #define PetscLogStagePop()            PETSC_SUCCESS
660   #define PetscLogStageSetActive(a, b)  ((void)(a), (void)(b), PETSC_SUCCESS)
661   #define PetscLogStageGetActive(a, b)  ((void)(a), *(b) = PETSC_FALSE, PETSC_SUCCESS)
662   #define PetscLogStageGetVisible(a, b) ((void)(a), *(b) = PETSC_FALSE, PETSC_SUCCESS)
663   #define PetscLogStageSetVisible(a, b) ((void)(a), (void)(b), PETSC_SUCCESS)
664   #define PetscLogStageGetId(a, b)      ((void)(a), *(b) = -1, PETSC_SUCCESS)
665   #define PetscLogStageGetName(a, b)    ((void)(a), *(b) = NULL, PETSC_SUCCESS)
666 
667   #define PetscLogEventRegister(a, b, c)    ((void)(a), (void)(b), *(c) = -1, PETSC_SUCCESS)
668   #define PetscLogEventSetCollective(a, b)  ((void)(a), (void)(b), PETSC_SUCCESS)
669   #define PetscLogEventIncludeClass(a)      ((void)(a), PETSC_SUCCESS)
670   #define PetscLogEventExcludeClass(a)      ((void)(a), PETSC_SUCCESS)
671   #define PetscLogEventActivate(a)          ((void)(a), PETSC_SUCCESS)
672   #define PetscLogEventDeactivate(a)        ((void)(a), PETSC_SUCCESS)
673   #define PetscLogEventDeactivatePush(a)    ((void)(a), PETSC_SUCCESS)
674   #define PetscLogEventDeactivatePop(a)     ((void)(a), PETSC_SUCCESS)
675   #define PetscLogEventActivateClass(a)     ((void)(a), PETSC_SUCCESS)
676   #define PetscLogEventDeactivateClass(a)   ((void)(a), PETSC_SUCCESS)
677   #define PetscLogEventSetActiveAll(a, b)   ((void)(a), PETSC_SUCCESS)
678   #define PetscLogEventGetId(a, b)          ((void)(a), *(b) = -1, PETSC_SUCCESS)
679   #define PetscLogEventGetName(a, b)        ((void)(a), *(b) = NULL, PETSC_SUCCESS)
680   #define PetscLogEventGetPerfInfo(a, b, c) ((void)(a), (void)(b), *(c) = (const PetscEventPerfInfo){0}, PETSC_SUCCESS)
681 
682   #define PetscLogEventSetDof(a, b, c)   ((void)(a), (void)(b), (void)(c), PETSC_SUCCESS)
683   #define PetscLogEventSetError(a, b, c) ((void)(a), (void)(b), (void)(c), PETSC_SUCCESS)
684   #define PetscLogEventsPause()          PETSC_SUCCESS
685   #define PetscLogEventsResume()         PETSC_SUCCESS
686 
687   #define PetscLogClassGetClassId(a, b) (*(b) = -1, PETSC_SUCCESS)
688   #define PetscLogClassIdGetName(a, b)  (*(b) = NULL, PETSC_SUCCESS)
689 
690 PETSC_UNUSED static PetscErrorCode (*PetscLogPLB)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject) = NULL;
691 PETSC_UNUSED static PetscErrorCode (*PetscLogPLE)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject) = NULL;
692 PETSC_UNUSED static PetscErrorCode (*PetscLogPHC)(PetscObject)                                                            = NULL;
693 PETSC_UNUSED static PetscErrorCode (*PetscLogPHD)(PetscObject)                                                            = NULL;
694 
695   #define PetscLogObjectCreate(h)        ((void)(h), PETSC_SUCCESS)
696   #define PetscLogObjectDestroy(h)       ((void)(h), PETSC_SUCCESS)
697   #define PetscLogObjectState(h, c, ...) ((void)(h), (void)(c), PETSC_SUCCESS)
698 
699   #define PetscLogDefaultBegin()                   PETSC_SUCCESS
700   #define PetscLogAllBegin()                       PETSC_SUCCESS
701   #define PetscLogNestedBegin()                    PETSC_SUCCESS
702   #define PetscLogTraceBegin(file)                 ((void)(file), PETSC_SUCCESS)
703   #define PetscLogMPEBegin()                       PETSC_SUCCESS
704   #define PetscLogPerfstubsBegin()                 PETSC_SUCCESS
705   #define PetscLogLegacyCallbacksBegin(a, b, c, d) ((void)(a), (void)(b), (void)(c), (void)(d), PETSC_SUCCESS)
706   #define PetscLogActions(a)                       ((void)(a), PETSC_SUCCESS)
707   #define PetscLogObjects(a)                       ((void)(a), PETSC_SUCCESS)
708   #define PetscLogSetThreshold(a, b)               ((void)(a), (void)(b), PETSC_SUCCESS)
709 
710   #define PetscLogSet(lb, le)    PETSC_SUCCESS
711   #define PetscLogIsActive(flag) (*(flag) = PETSC_FALSE, PETSC_SUCCESS)
712 
713   #define PetscLogView(viewer)      ((void)(viewer), PETSC_SUCCESS)
714   #define PetscLogViewFromOptions() PETSC_SUCCESS
715   #define PetscLogDump(c)           ((void)(c), PETSC_SUCCESS)
716   #define PetscLogMPEDump(c)        ((void)(c), PETSC_SUCCESS)
717 
718   #define PetscLogEventSync(e, comm)                            ((void)(e), (void)(comm), PETSC_SUCCESS)
719   #define PetscLogEventBegin(e, o1, o2, o3, o4)                 ((void)(e), (void)(o1), (void)(o2), (void)(o3), PETSC_SUCCESS)
720   #define PetscLogEventEnd(e, o1, o2, o3, o4)                   ((void)(e), (void)(o1), (void)(o2), (void)(o3), PETSC_SUCCESS)
721 
722   /* If PETSC_USE_LOG is NOT defined, these still need to be! */
723   #define MPI_Startall_irecv(count, datatype, number, requests) ((number) && MPI_Startall(number, requests))
724   #define MPI_Startall_isend(count, datatype, number, requests) ((number) && MPI_Startall(number, requests))
725   #define MPI_Start_isend(count, datatype, requests)            MPI_Start(requests)
726 
727 #endif /* PETSC_USE_LOG */
728 
729 #define PetscPreLoadBegin(flag, name) \
730   do { \
731     PetscBool     PetscPreLoading = flag; \
732     int           PetscPreLoadMax, PetscPreLoadIt; \
733     PetscLogStage _stageNum; \
734     PetscCall(PetscOptionsGetBool(NULL, NULL, "-preload", &PetscPreLoading, NULL)); \
735     PetscPreLoadMax     = (int)(PetscPreLoading); \
736     PetscPreLoadingUsed = PetscPreLoading ? PETSC_TRUE : PetscPreLoadingUsed; \
737     for (PetscPreLoadIt = 0; PetscPreLoadIt <= PetscPreLoadMax; PetscPreLoadIt++) { \
738       PetscPreLoadingOn = PetscPreLoading; \
739       PetscCall(PetscBarrier(NULL)); \
740       if (PetscPreLoadIt > 0) PetscCall(PetscLogStageGetId(name, &_stageNum)); \
741       else PetscCall(PetscLogStageRegister(name, &_stageNum)); \
742       PetscCall(PetscLogStageSetActive(_stageNum, (PetscBool)(!PetscPreLoadMax || PetscPreLoadIt))); \
743       PetscCall(PetscLogStagePush(_stageNum))
744 
745 #define PetscPreLoadEnd() \
746   PetscCall(PetscLogStagePop()); \
747   PetscPreLoading = PETSC_FALSE; \
748   } \
749   } \
750   while (0)
751 
752 #define PetscPreLoadStage(name) \
753   do { \
754     PetscCall(PetscLogStagePop()); \
755     if (PetscPreLoadIt > 0) PetscCall(PetscLogStageGetId(name, &_stageNum)); \
756     else PetscCall(PetscLogStageRegister(name, &_stageNum)); \
757     PetscCall(PetscLogStageSetActive(_stageNum, (PetscBool)(!PetscPreLoadMax || PetscPreLoadIt))); \
758     PetscCall(PetscLogStagePush(_stageNum)); \
759   } while (0)
760 
761 /* some vars for logging */
762 PETSC_EXTERN PetscBool PetscPreLoadingUsed; /* true if we are or have done preloading */
763 PETSC_EXTERN PetscBool PetscPreLoadingOn;   /* true if we are currently in a preloading calculation */
764 
765 #if defined(PETSC_USE_LOG) && defined(PETSC_HAVE_DEVICE)
766 
767 PETSC_EXTERN PetscErrorCode PetscLogGpuTime(void);
768 PETSC_EXTERN PetscErrorCode PetscLogGpuTimeBegin(void);
769 PETSC_EXTERN PetscErrorCode PetscLogGpuTimeEnd(void);
770 
771 /*@C
772        PetscLogGpuFlops - Log how many flops are performed in a calculation on the device
773 
774    Input Parameter:
775 .   flops - the number of flops
776 
777    Level: intermediate
778 
779    Notes:
780      To limit the chance of integer overflow when multiplying by a constant, represent the constant as a double,
781      not an integer. Use `PetscLogFlops`(4.0*n) not `PetscLogFlops`(4*n)
782 
783      The values are also added to the total flop count for the MPI rank that is set with `PetscLogFlops()`; hence the number of flops
784      just on the CPU would be the value from set from `PetscLogFlops()` minus the value set from `PetscLogGpuFlops()`
785 
786 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogFlops()`, `PetscLogGpuTimeBegin()`, `PetscLogGpuTimeEnd()`
787 @*/
788 static inline PetscErrorCode PetscLogGpuFlops(PetscLogDouble n)
789 {
790   PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot log negative flops");
791   PetscCall(PetscAddLogDouble(&petsc_TotalFlops, &petsc_TotalFlops_th, PETSC_FLOPS_PER_OP * n));
792   PetscCall(PetscAddLogDouble(&petsc_gflops, &petsc_gflops_th, PETSC_FLOPS_PER_OP * n));
793   return PETSC_SUCCESS;
794 }
795 
796 static inline PetscErrorCode PetscLogGpuTimeAdd(PetscLogDouble t)
797 {
798   return PetscAddLogDouble(&petsc_gtime, &petsc_gtime_th, t);
799 }
800 
801 static inline PetscErrorCode PetscLogCpuToGpu(PetscLogDouble size)
802 {
803   return PetscAddLogDoubleCnt(&petsc_ctog_ct, &petsc_ctog_sz, &petsc_ctog_ct_th, &petsc_ctog_sz_th, size);
804 }
805 
806 static inline PetscErrorCode PetscLogGpuToCpu(PetscLogDouble size)
807 {
808   return PetscAddLogDoubleCnt(&petsc_gtoc_ct, &petsc_gtoc_sz, &petsc_gtoc_ct_th, &petsc_gtoc_sz_th, size);
809 }
810 
811 static inline PetscErrorCode PetscLogCpuToGpuScalar(PetscLogDouble size)
812 {
813   return PetscAddLogDoubleCnt(&petsc_ctog_ct_scalar, &petsc_ctog_sz_scalar, &petsc_ctog_ct_scalar_th, &petsc_ctog_sz_scalar_th, size);
814 }
815 
816 static inline PetscErrorCode PetscLogGpuToCpuScalar(PetscLogDouble size)
817 {
818   return PetscAddLogDoubleCnt(&petsc_gtoc_ct_scalar, &petsc_gtoc_sz_scalar, &petsc_gtoc_ct_scalar_th, &petsc_gtoc_sz_scalar_th, size);
819 }
820 #else
821 
822   #define PetscLogCpuToGpu(a)       PETSC_SUCCESS
823   #define PetscLogGpuToCpu(a)       PETSC_SUCCESS
824   #define PetscLogCpuToGpuScalar(a) PETSC_SUCCESS
825   #define PetscLogGpuToCpuScalar(a) PETSC_SUCCESS
826   #define PetscLogGpuFlops(a)       PETSC_SUCCESS
827   #define PetscLogGpuTime()         PETSC_SUCCESS
828   #define PetscLogGpuTimeAdd(a)     PETSC_SUCCESS
829   #define PetscLogGpuTimeBegin()    PETSC_SUCCESS
830   #define PetscLogGpuTimeEnd()      PETSC_SUCCESS
831 
832 #endif /* PETSC_USE_LOG && PETSC_HAVE_DEVICE */
833 
834 /* remove TLS defines */
835 #undef PETSC_EXTERN_TLS
836 #undef PETSC_TLS
837 
838 #endif
839