xref: /petsc/include/petsclog.h (revision 6f933394ea0da1dbc01e2ca6853fb6eed18e5571)
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 /* Handle multithreading */
138 #if defined(PETSC_HAVE_THREADSAFETY)
139   #if defined(__cplusplus)
140     #define PETSC_TLS thread_local
141   #else
142     #define PETSC_TLS _Thread_local
143   #endif
144   #define PETSC_EXTERN_TLS extern PETSC_TLS PETSC_VISIBILITY_PUBLIC
145 PETSC_EXTERN PetscErrorCode PetscAddLogDouble(PetscLogDouble *, PetscLogDouble *, PetscLogDouble);
146 PETSC_EXTERN PetscErrorCode PetscAddLogDoubleCnt(PetscLogDouble *, PetscLogDouble *, PetscLogDouble *, PetscLogDouble *, PetscLogDouble);
147 #else
148   #define PETSC_EXTERN_TLS PETSC_EXTERN
149   #define PETSC_TLS
150   #define PetscAddLogDouble(a, b, c)          ((PetscErrorCode)((*(a) += (c), PETSC_SUCCESS) || ((*(b) += (c)), PETSC_SUCCESS)))
151   #define PetscAddLogDoubleCnt(a, b, c, d, e) ((PetscErrorCode)(PetscAddLogDouble(a, c, 1) || PetscAddLogDouble(b, d, e)))
152 #endif
153 
154 /*
155     PetscClassRegInfo, PetscClassPerfInfo - Each class has two data structures associated with it. The first has
156        static information about it, the second collects statistics on how many objects of the class are created,
157        how much memory they use, etc.
158 
159     PetscClassRegLog, PetscClassPerfLog - arrays of the PetscClassRegInfo and PetscClassPerfInfo for all classes.
160 */
161 typedef struct {
162   char        *name;    /* The class name */
163   PetscClassId classid; /* The integer identifying this class */
164 } PetscClassRegInfo;
165 
166 typedef struct {
167   PetscClassId   id;           /* The integer identifying this class */
168   int            creations;    /* The number of objects of this class created */
169   int            destructions; /* The number of objects of this class destroyed */
170   PetscLogDouble mem;          /* The total memory allocated by objects of this class; this is completely wrong and should possibly be removed */
171   PetscLogDouble descMem;      /* The total memory allocated by descendents of these objects; this is completely wrong and should possibly be removed */
172 } PetscClassPerfInfo;
173 
174 typedef struct _n_PetscClassRegLog *PetscClassRegLog;
175 struct _n_PetscClassRegLog {
176   int                numClasses; /* The number of classes registered */
177   int                maxClasses; /* The maximum number of classes */
178   PetscClassRegInfo *classInfo;  /* The structure for class information (classids are monotonicly increasing) */
179 };
180 
181 typedef struct _n_PetscClassPerfLog *PetscClassPerfLog;
182 struct _n_PetscClassPerfLog {
183   int                 numClasses; /* The number of logging classes */
184   int                 maxClasses; /* The maximum number of classes */
185   PetscClassPerfInfo *classInfo;  /* The structure for class information (classids are monotonicly increasing) */
186 };
187 
188 /*
189     PetscEventRegInfo, PetscEventPerfInfo - Each event has two data structures associated with it. The first has
190        static information about it, the second collects statistics on how many times the event is used, how
191        much time it takes, etc.
192 
193     PetscEventRegLog, PetscEventPerfLog - an array of all PetscEventRegInfo and PetscEventPerfInfo for all events. There is one
194       of these for each stage.
195 
196 */
197 typedef struct {
198   char        *name;       /* The name of this event */
199   PetscClassId classid;    /* The class the event is associated with */
200   PetscBool    collective; /* Flag this event as collective */
201 #if defined(PETSC_HAVE_TAU_PERFSTUBS)
202   void *timer; /* Associated external tool timer for this event */
203 #endif
204 #if defined(PETSC_HAVE_MPE)
205   int mpe_id_begin; /* MPE IDs that define the event */
206   int mpe_id_end;
207 #endif
208 } PetscEventRegInfo;
209 
210 typedef struct _n_PetscEventRegLog *PetscEventRegLog;
211 struct _n_PetscEventRegLog {
212   int                numEvents; /* The number of registered events */
213   int                maxEvents; /* The maximum number of events */
214   PetscEventRegInfo *eventInfo; /* The registration information for each event */
215 };
216 
217 typedef struct _n_PetscEventPerfLog *PetscEventPerfLog;
218 struct _n_PetscEventPerfLog {
219   int                 numEvents; /* The number of logging events */
220   int                 maxEvents; /* The maximum number of events */
221   PetscEventPerfInfo *eventInfo; /* The performance information for each event */
222 };
223 
224 /*
225    PetscStageInfo - Contains all the information about a particular stage.
226 
227    PetscStageLog - An array of PetscStageInfo for each registered stage. There is a single one of these in the code.
228 */
229 typedef struct _PetscStageInfo {
230   char              *name;     /* The stage name */
231   PetscBool          used;     /* The stage was pushed on this processor */
232   PetscEventPerfInfo perfInfo; /* The stage performance information */
233   PetscEventPerfLog  eventLog; /* The event information for this stage */
234   PetscClassPerfLog  classLog; /* The class information for this stage */
235 #if defined(PETSC_HAVE_TAU_PERFSTUBS)
236   void *timer; /* Associated external tool timer for this stage */
237 #endif
238 } PetscStageInfo;
239 
240 typedef struct _n_PetscStageLog *PetscStageLog;
241 struct _n_PetscStageLog {
242   int              numStages; /* The number of registered stages */
243   int              maxStages; /* The maximum number of stages */
244   PetscIntStack    stack;     /* The stack for active stages */
245   int              curStage;  /* The current stage (only used in macros so we don't call PetscIntStackTop) */
246   PetscStageInfo  *stageInfo; /* The information for each stage */
247   PetscEventRegLog eventLog;  /* The registered events */
248   PetscClassRegLog classLog;  /* The registered classes */
249 };
250 
251 PETSC_DEPRECATED_FUNCTION(3, 18, 0, "PetscLogObjectParent()", ) static inline PetscErrorCode PetscLogObjectParent(PetscObject o, PetscObject p)
252 {
253   (void)o;
254   (void)p;
255   return PETSC_SUCCESS;
256 }
257 
258 PETSC_DEPRECATED_FUNCTION(3, 18, 0, "PetscLogObjectMemory()", ) static inline PetscErrorCode PetscLogObjectMemory(PetscObject o, PetscLogDouble m)
259 {
260   (void)o;
261   (void)m;
262   return PETSC_SUCCESS;
263 }
264 
265 #if defined(PETSC_USE_LOG) /* --- Logging is turned on --------------------------------*/
266 PETSC_EXTERN PetscStageLog  petsc_stageLog;
267 PETSC_EXTERN PetscErrorCode PetscLogGetStageLog(PetscStageLog *);
268 PETSC_EXTERN PetscErrorCode PetscStageLogGetCurrent(PetscStageLog, int *);
269 PETSC_EXTERN PetscErrorCode PetscStageLogGetEventPerfLog(PetscStageLog, int, PetscEventPerfLog *);
270 
271 PETSC_EXTERN PetscErrorCode PetscGetFlops(PetscLogDouble *);
272 
273   #if defined(PETSC_HAVE_MPE)
274 PETSC_EXTERN PetscErrorCode PetscLogMPEBegin(void);
275 PETSC_EXTERN PetscErrorCode PetscLogMPEDump(const char[]);
276   #endif
277 
278 PETSC_EXTERN PetscErrorCode (*PetscLogPLB)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject);
279 PETSC_EXTERN PetscErrorCode (*PetscLogPLE)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject);
280 PETSC_EXTERN PetscErrorCode (*PetscLogPHC)(PetscObject);
281 PETSC_EXTERN PetscErrorCode (*PetscLogPHD)(PetscObject);
282 
283   #define PetscLogObjectParents(p, n, d) PetscMacroReturnStandard(for (int _i = 0; _i < (n); ++_i) PetscCall(PetscLogObjectParent((PetscObject)(p), (PetscObject)(d)[_i]));)
284   #define PetscLogObjectCreate(h)        ((PetscLogPHC) ? (*PetscLogPHC)((PetscObject)(h)) : PETSC_SUCCESS)
285   #define PetscLogObjectDestroy(h)       ((PetscLogPHD) ? (*PetscLogPHD)((PetscObject)(h)) : PETSC_SUCCESS)
286 PETSC_EXTERN PetscErrorCode PetscLogObjectState(PetscObject, const char[], ...) PETSC_ATTRIBUTE_FORMAT(2, 3);
287 
288 /* Initialization functions */
289 PETSC_EXTERN PetscErrorCode PetscLogDefaultBegin(void);
290 PETSC_EXTERN PetscErrorCode PetscLogAllBegin(void);
291 PETSC_EXTERN PetscErrorCode PetscLogNestedBegin(void);
292 PETSC_EXTERN PetscErrorCode PetscLogTraceBegin(FILE *);
293 PETSC_EXTERN PetscErrorCode PetscLogActions(PetscBool);
294 PETSC_EXTERN PetscErrorCode PetscLogObjects(PetscBool);
295 PETSC_EXTERN PetscErrorCode PetscLogSetThreshold(PetscLogDouble, PetscLogDouble *);
296 PETSC_EXTERN PetscErrorCode PetscLogSet(PetscErrorCode (*)(int, int, PetscObject, PetscObject, PetscObject, PetscObject), PetscErrorCode (*)(int, int, PetscObject, PetscObject, PetscObject, PetscObject));
297 
298 /* Output functions */
299 PETSC_EXTERN PetscErrorCode PetscLogView(PetscViewer);
300 PETSC_EXTERN PetscErrorCode PetscLogViewFromOptions(void);
301 PETSC_EXTERN PetscErrorCode PetscLogDump(const char[]);
302 
303 /* Status checking functions */
304 PETSC_EXTERN PetscErrorCode PetscLogIsActive(PetscBool *);
305 
306 /* Stage functions */
307 PETSC_EXTERN PetscErrorCode PetscLogStageRegister(const char[], PetscLogStage *);
308 PETSC_EXTERN PetscErrorCode PetscLogStagePush(PetscLogStage);
309 PETSC_EXTERN PetscErrorCode PetscLogStagePop(void);
310 PETSC_EXTERN PetscErrorCode PetscLogStageSetActive(PetscLogStage, PetscBool);
311 PETSC_EXTERN PetscErrorCode PetscLogStageGetActive(PetscLogStage, PetscBool *);
312 PETSC_EXTERN PetscErrorCode PetscLogStageSetVisible(PetscLogStage, PetscBool);
313 PETSC_EXTERN PetscErrorCode PetscLogStageGetVisible(PetscLogStage, PetscBool *);
314 PETSC_EXTERN PetscErrorCode PetscLogStageGetId(const char[], PetscLogStage *);
315 
316 /* Event functions */
317 PETSC_EXTERN PetscErrorCode PetscLogEventRegister(const char[], PetscClassId, PetscLogEvent *);
318 PETSC_EXTERN PetscErrorCode PetscLogEventSetCollective(PetscLogEvent, PetscBool);
319 PETSC_EXTERN PetscErrorCode PetscLogEventIncludeClass(PetscClassId);
320 PETSC_EXTERN PetscErrorCode PetscLogEventExcludeClass(PetscClassId);
321 PETSC_EXTERN PetscErrorCode PetscLogEventActivate(PetscLogEvent);
322 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivate(PetscLogEvent);
323 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivatePush(PetscLogEvent);
324 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivatePop(PetscLogEvent);
325 PETSC_EXTERN PetscErrorCode PetscLogEventSetActiveAll(PetscLogEvent, PetscBool);
326 PETSC_EXTERN PetscErrorCode PetscLogEventActivateClass(PetscClassId);
327 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivateClass(PetscClassId);
328 PETSC_EXTERN PetscErrorCode PetscLogEventGetId(const char[], PetscLogEvent *);
329 PETSC_EXTERN PetscErrorCode PetscLogEventGetPerfInfo(int, PetscLogEvent, PetscEventPerfInfo *);
330 PETSC_EXTERN PetscErrorCode PetscLogEventSetDof(PetscLogEvent, PetscInt, PetscLogDouble);
331 PETSC_EXTERN PetscErrorCode PetscLogEventSetError(PetscLogEvent, PetscInt, PetscLogDouble);
332 PETSC_EXTERN PetscErrorCode PetscLogPushCurrentEvent_Internal(PetscLogEvent);
333 PETSC_EXTERN PetscErrorCode PetscLogPopCurrentEvent_Internal(void);
334 
335 PETSC_EXTERN PetscBool PetscLogMemory;
336 
337 PETSC_EXTERN PetscBool      PetscLogSyncOn; /* true if logging synchronization is enabled */
338 PETSC_EXTERN PetscErrorCode PetscLogEventSynchronize(PetscLogEvent, MPI_Comm);
339 
340   #define PetscLogEventSync(e, comm) \
341     ((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)))
342 
343   #define PetscLogEventBegin(e, o1, o2, o3, o4) \
344     ((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))
345 
346   #define PetscLogEventEnd(e, o1, o2, o3, o4) \
347     ((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))
348 
349 PETSC_EXTERN PetscErrorCode PetscLogEventGetFlops(PetscLogEvent, PetscLogDouble *);
350 PETSC_EXTERN PetscErrorCode PetscLogEventZeroFlops(PetscLogEvent);
351 
352 /* Global flop counter */
353 PETSC_EXTERN PetscLogDouble petsc_TotalFlops;
354 PETSC_EXTERN PetscLogDouble petsc_irecv_ct;
355 PETSC_EXTERN PetscLogDouble petsc_isend_ct;
356 PETSC_EXTERN PetscLogDouble petsc_recv_ct;
357 PETSC_EXTERN PetscLogDouble petsc_send_ct;
358 PETSC_EXTERN PetscLogDouble petsc_irecv_len;
359 PETSC_EXTERN PetscLogDouble petsc_isend_len;
360 PETSC_EXTERN PetscLogDouble petsc_recv_len;
361 PETSC_EXTERN PetscLogDouble petsc_send_len;
362 PETSC_EXTERN PetscLogDouble petsc_allreduce_ct;
363 PETSC_EXTERN PetscLogDouble petsc_gather_ct;
364 PETSC_EXTERN PetscLogDouble petsc_scatter_ct;
365 PETSC_EXTERN PetscLogDouble petsc_wait_ct;
366 PETSC_EXTERN PetscLogDouble petsc_wait_any_ct;
367 PETSC_EXTERN PetscLogDouble petsc_wait_all_ct;
368 PETSC_EXTERN PetscLogDouble petsc_sum_of_waits_ct;
369 
370 /* Thread local storage */
371 PETSC_EXTERN_TLS PetscLogDouble petsc_TotalFlops_th;
372 PETSC_EXTERN_TLS PetscLogDouble petsc_irecv_ct_th;
373 PETSC_EXTERN_TLS PetscLogDouble petsc_isend_ct_th;
374 PETSC_EXTERN_TLS PetscLogDouble petsc_recv_ct_th;
375 PETSC_EXTERN_TLS PetscLogDouble petsc_send_ct_th;
376 PETSC_EXTERN_TLS PetscLogDouble petsc_irecv_len_th;
377 PETSC_EXTERN_TLS PetscLogDouble petsc_isend_len_th;
378 PETSC_EXTERN_TLS PetscLogDouble petsc_recv_len_th;
379 PETSC_EXTERN_TLS PetscLogDouble petsc_send_len_th;
380 PETSC_EXTERN_TLS PetscLogDouble petsc_allreduce_ct_th;
381 PETSC_EXTERN_TLS PetscLogDouble petsc_gather_ct_th;
382 PETSC_EXTERN_TLS PetscLogDouble petsc_scatter_ct_th;
383 PETSC_EXTERN_TLS PetscLogDouble petsc_wait_ct_th;
384 PETSC_EXTERN_TLS PetscLogDouble petsc_wait_any_ct_th;
385 PETSC_EXTERN_TLS PetscLogDouble petsc_wait_all_ct_th;
386 PETSC_EXTERN_TLS PetscLogDouble petsc_sum_of_waits_ct_th;
387 
388   /*
389    Flop counting:  We count each arithmetic operation (e.g., addition, multiplication) separately.
390 
391    For the complex numbers version, note that
392        1 complex addition = 2 flops
393        1 complex multiplication = 6 flops,
394    where we define 1 flop as that for a double precision scalar.  We roughly approximate
395    flop counting for complex numbers by multiplying the total flops by 4; this corresponds
396    to the assumption that we're counting mostly additions and multiplications -- and
397    roughly the same number of each.  More accurate counting could be done by distinguishing
398    among the various arithmetic operations.
399  */
400 
401   #if defined(PETSC_USE_COMPLEX)
402     #define PETSC_FLOPS_PER_OP 4.0
403   #else
404     #define PETSC_FLOPS_PER_OP 1.0
405   #endif
406 
407 /*@C
408        PetscLogFlops - Log how many flops are performed in a calculation
409 
410    Input Parameter:
411 .   flops - the number of flops
412 
413    Level: intermediate
414 
415    Note:
416      To limit the chance of integer overflow when multiplying by a constant, represent the constant as a double,
417      not an integer. Use `PetscLogFlops`(4.0*n) not `PetscLogFlops`(4*n)
418 
419 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`
420 @*/
421 static inline PetscErrorCode PetscLogFlops(PetscLogDouble n)
422 {
423   PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot log negative flops");
424   return PetscAddLogDouble(&petsc_TotalFlops, &petsc_TotalFlops_th, PETSC_FLOPS_PER_OP * n);
425 }
426 
427   /*
428      These are used internally in the PETSc routines to keep a count of MPI messages and
429    their sizes.
430 
431      This does not work for MPI-Uni because our include/petsc/mpiuni/mpi.h file
432    uses macros to defined the MPI operations.
433 
434      It does not work correctly from HP-UX because it processes the
435    macros in a way that sometimes it double counts, hence
436    PETSC_HAVE_BROKEN_RECURSIVE_MACRO
437 
438      It does not work with Windows because winmpich lacks MPI_Type_size()
439 */
440   #if !defined(MPIUNI_H) && !defined(PETSC_HAVE_BROKEN_RECURSIVE_MACRO)
441 /*
442    Logging of MPI activities
443 */
444 static inline PetscErrorCode PetscMPITypeSize(PetscInt count, MPI_Datatype type, PetscLogDouble *length, PetscLogDouble *length_th)
445 {
446   PetscMPIInt typesize;
447 
448   if (type == MPI_DATATYPE_NULL) return PETSC_SUCCESS;
449   PetscCallMPI(MPI_Type_size(type, &typesize));
450   return PetscAddLogDouble(length, length_th, (PetscLogDouble)(count * typesize));
451 }
452 
453 static inline PetscErrorCode PetscMPITypeSizeComm(MPI_Comm comm, const PetscMPIInt *counts, MPI_Datatype type, PetscLogDouble *length, PetscLogDouble *length_th)
454 {
455   PetscMPIInt    typesize, size, p;
456   PetscLogDouble l;
457 
458   if (type == MPI_DATATYPE_NULL) return PETSC_SUCCESS;
459   PetscCallMPI(MPI_Comm_size(comm, &size));
460   PetscCallMPI(MPI_Type_size(type, &typesize));
461   for (p = 0, l = 0.0; p < size; ++p) l += (PetscLogDouble)(counts[p] * typesize);
462   return PetscAddLogDouble(length, length_th, l);
463 }
464 
465 /*
466     Returns 1 if the communicator is parallel else zero
467 */
468 static inline int PetscMPIParallelComm(MPI_Comm comm)
469 {
470   PetscMPIInt size;
471   MPI_Comm_size(comm, &size);
472   return size > 1;
473 }
474 
475     #define MPI_Irecv(buf, count, datatype, source, tag, comm, request) \
476       (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)))
477 
478     #define MPI_Irecv_c(buf, count, datatype, source, tag, comm, request) \
479       (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)))
480 
481     #define MPI_Isend(buf, count, datatype, dest, tag, comm, request) \
482       (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)))
483 
484     #define MPI_Isend_c(buf, count, datatype, dest, tag, comm, request) \
485       (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)))
486 
487     #define MPI_Startall_irecv(count, datatype, number, requests) \
488       (PetscAddLogDouble(&petsc_irecv_ct, &petsc_irecv_ct_th, number) || PetscMPITypeSize((count), (datatype), &(petsc_irecv_len), &(petsc_irecv_len_th)) || ((number) && MPI_Startall((number), (requests))))
489 
490     #define MPI_Startall_isend(count, datatype, number, requests) \
491       (PetscAddLogDouble(&petsc_isend_ct, &petsc_isend_ct_th, number) || PetscMPITypeSize((count), (datatype), &(petsc_isend_len), &(petsc_isend_len_th)) || ((number) && MPI_Startall((number), (requests))))
492 
493     #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)))
494 
495     #define MPI_Recv(buf, count, datatype, source, tag, comm, status) \
496       (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)))
497 
498     #define MPI_Recv_c(buf, count, datatype, source, tag, comm, status) \
499       (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)))
500 
501     #define MPI_Send(buf, count, datatype, dest, tag, comm) \
502       (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)))
503 
504     #define MPI_Send_c(buf, count, datatype, dest, tag, comm) \
505       (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)))
506 
507     #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)))
508 
509     #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)))
510 
511     #define MPI_Waitall(count, array_of_requests, array_of_statuses) \
512       (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)))
513 
514     #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)))
515 
516     #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)))
517 
518     #define MPI_Reduce_scatter_block(sendbuf, recvbuf, recvcount, datatype, op, comm) \
519       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || MPI_Reduce_scatter_block((sendbuf), (recvbuf), (recvcount), (datatype), (op), (comm)))
520 
521     #define MPI_Alltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm) \
522       (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)))
523 
524     #define MPI_Alltoallv(sendbuf, sendcnts, sdispls, sendtype, recvbuf, recvcnts, rdispls, recvtype, comm) \
525       (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)))
526 
527     #define MPI_Allgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm) \
528       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Allgather((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (comm)))
529 
530     #define MPI_Allgatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, comm) \
531       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Allgatherv((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (displs), (recvtype), (comm)))
532 
533     #define MPI_Gather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm) \
534       (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)))
535 
536     #define MPI_Gatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, root, comm) \
537       (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)))
538 
539     #define MPI_Scatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm) \
540       (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)))
541 
542     #define MPI_Scatterv(sendbuf, sendcount, displs, sendtype, recvbuf, recvcount, recvtype, root, comm) \
543       (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)))
544 
545     #define MPI_Ialltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm, request) \
546       (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)))
547 
548     #define MPI_Ialltoallv(sendbuf, sendcnts, sdispls, sendtype, recvbuf, recvcnts, rdispls, recvtype, comm, request) \
549       (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)))
550 
551     #define MPI_Iallgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm, request) \
552       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Iallgather((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (comm), (request)))
553 
554     #define MPI_Iallgatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, comm, request) \
555       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Iallgatherv((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (displs), (recvtype), (comm), (request)))
556 
557     #define MPI_Igather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm, request) \
558       (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)))
559 
560     #define MPI_Igatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, root, comm, request) \
561       (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)))
562 
563     #define MPI_Iscatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm, request) \
564       (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)))
565 
566     #define MPI_Iscatterv(sendbuf, sendcount, displs, sendtype, recvbuf, recvcount, recvtype, root, comm, request) \
567       (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)))
568 
569     #define MPIX_Send_enqueue(buf, count, datatype, dest, tag, comm) \
570       (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)))
571 
572     #define MPIX_Recv_enqueue(buf, count, datatype, source, tag, comm, status) \
573       (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)))
574 
575     #define MPIX_Isend_enqueue(buf, count, datatype, dest, tag, comm, request) \
576       (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)))
577 
578     #define MPIX_Irecv_enqueue(buf, count, datatype, source, tag, comm, request) \
579       (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)))
580 
581     #define MPIX_Allreduce_enqueue(sendbuf, recvbuf, count, datatype, op, comm) \
582       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || MPIX_Allreduce_enqueue((sendbuf), (recvbuf), (count), (datatype), (op), (comm)))
583 
584     #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)))
585 
586     #define MPIX_Waitall_enqueue(count, array_of_requests, array_of_statuses) \
587       (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)))
588   #else
589 
590     #define MPI_Startall_irecv(count, datatype, number, requests) ((number) && MPI_Startall((number), (requests)))
591 
592     #define MPI_Startall_isend(count, datatype, number, requests) ((number) && MPI_Startall((number), (requests)))
593 
594     #define MPI_Start_isend(count, datatype, requests) (MPI_Start((requests)))
595 
596   #endif /* !MPIUNI_H && ! PETSC_HAVE_BROKEN_RECURSIVE_MACRO */
597 
598 #else /* ---Logging is turned off --------------------------------------------*/
599 
600   #define PetscLogMemory PETSC_FALSE
601 
602   #define PetscLogFlops(n) ((void)(n), PETSC_SUCCESS)
603   #define PetscGetFlops(a) (*(a) = 0.0, PETSC_SUCCESS)
604 
605   #define PetscLogStageRegister(a, b)   PETSC_SUCCESS
606   #define PetscLogStagePush(a)          PETSC_SUCCESS
607   #define PetscLogStagePop()            PETSC_SUCCESS
608   #define PetscLogStageSetActive(a, b)  PETSC_SUCCESS
609   #define PetscLogStageGetActive(a, b)  PETSC_SUCCESS
610   #define PetscLogStageGetVisible(a, b) PETSC_SUCCESS
611   #define PetscLogStageSetVisible(a, b) PETSC_SUCCESS
612   #define PetscLogStageGetId(a, b)      (*(b) = 0, PETSC_SUCCESS)
613 
614   #define PetscLogEventRegister(a, b, c)    PETSC_SUCCESS
615   #define PetscLogEventSetCollective(a, b)  PETSC_SUCCESS
616   #define PetscLogEventIncludeClass(a)      PETSC_SUCCESS
617   #define PetscLogEventExcludeClass(a)      PETSC_SUCCESS
618   #define PetscLogEventActivate(a)          PETSC_SUCCESS
619   #define PetscLogEventDeactivate(a)        PETSC_SUCCESS
620   #define PetscLogEventDeactivatePush(a)    PETSC_SUCCESS
621   #define PetscLogEventDeactivatePop(a)     PETSC_SUCCESS
622   #define PetscLogEventActivateClass(a)     PETSC_SUCCESS
623   #define PetscLogEventDeactivateClass(a)   PETSC_SUCCESS
624   #define PetscLogEventSetActiveAll(a, b)   PETSC_SUCCESS
625   #define PetscLogEventGetId(a, b)          (*(b) = 0, PETSC_SUCCESS)
626   #define PetscLogEventGetPerfInfo(a, b, c) PETSC_SUCCESS
627   #define PetscLogEventSetDof(a, b, c)      PETSC_SUCCESS
628   #define PetscLogEventSetError(a, b, c)    PETSC_SUCCESS
629 
630   #define PetscLogPLB PETSC_SUCCESS
631   #define PetscLogPLE PETSC_SUCCESS
632   #define PetscLogPHC PETSC_SUCCESS
633   #define PetscLogPHD PETSC_SUCCESS
634 
635   #define PetscLogObjectParents(p, n, c) PETSC_SUCCESS
636   #define PetscLogObjectCreate(h)        PETSC_SUCCESS
637   #define PetscLogObjectDestroy(h)       PETSC_SUCCESS
638 PETSC_EXTERN PetscErrorCode PetscLogObjectState(PetscObject, const char[], ...) PETSC_ATTRIBUTE_FORMAT(2, 3);
639 
640   #define PetscLogDefaultBegin()     PETSC_SUCCESS
641   #define PetscLogAllBegin()         PETSC_SUCCESS
642   #define PetscLogNestedBegin()      PETSC_SUCCESS
643   #define PetscLogTraceBegin(file)   PETSC_SUCCESS
644   #define PetscLogActions(a)         PETSC_SUCCESS
645   #define PetscLogObjects(a)         PETSC_SUCCESS
646   #define PetscLogSetThreshold(a, b) PETSC_SUCCESS
647   #define PetscLogSet(lb, le)        PETSC_SUCCESS
648   #define PetscLogIsActive(flag)     (*(flag) = PETSC_FALSE, PETSC_SUCCESS)
649 
650   #define PetscLogView(viewer)      PETSC_SUCCESS
651   #define PetscLogViewFromOptions() PETSC_SUCCESS
652   #define PetscLogDump(c)           PETSC_SUCCESS
653 
654   #define PetscLogEventSync(e, comm)                            PETSC_SUCCESS
655   #define PetscLogEventBegin(e, o1, o2, o3, o4)                 PETSC_SUCCESS
656   #define PetscLogEventEnd(e, o1, o2, o3, o4)                   PETSC_SUCCESS
657 
658   /* If PETSC_USE_LOG is NOT defined, these still need to be! */
659   #define MPI_Startall_irecv(count, datatype, number, requests) ((number) && MPI_Startall(number, requests))
660   #define MPI_Startall_isend(count, datatype, number, requests) ((number) && MPI_Startall(number, requests))
661   #define MPI_Start_isend(count, datatype, requests)            MPI_Start(requests)
662 
663 #endif /* PETSC_USE_LOG */
664 
665 #define PetscPreLoadBegin(flag, name) \
666   do { \
667     PetscBool     PetscPreLoading = flag; \
668     int           PetscPreLoadMax, PetscPreLoadIt; \
669     PetscLogStage _stageNum; \
670     PetscCall(PetscOptionsGetBool(NULL, NULL, "-preload", &PetscPreLoading, NULL)); \
671     PetscPreLoadMax     = (int)(PetscPreLoading); \
672     PetscPreLoadingUsed = PetscPreLoading ? PETSC_TRUE : PetscPreLoadingUsed; \
673     for (PetscPreLoadIt = 0; PetscPreLoadIt <= PetscPreLoadMax; PetscPreLoadIt++) { \
674       PetscPreLoadingOn = PetscPreLoading; \
675       PetscCall(PetscBarrier(NULL)); \
676       if (PetscPreLoadIt > 0) PetscCall(PetscLogStageGetId(name, &_stageNum)); \
677       else PetscCall(PetscLogStageRegister(name, &_stageNum)); \
678       PetscCall(PetscLogStageSetActive(_stageNum, (PetscBool)(!PetscPreLoadMax || PetscPreLoadIt))); \
679       PetscCall(PetscLogStagePush(_stageNum))
680 
681 #define PetscPreLoadEnd() \
682   PetscCall(PetscLogStagePop()); \
683   PetscPreLoading = PETSC_FALSE; \
684   } \
685   } \
686   while (0)
687 
688 #define PetscPreLoadStage(name) \
689   do { \
690     PetscCall(PetscLogStagePop()); \
691     if (PetscPreLoadIt > 0) PetscCall(PetscLogStageGetId(name, &_stageNum)); \
692     else PetscCall(PetscLogStageRegister(name, &_stageNum)); \
693     PetscCall(PetscLogStageSetActive(_stageNum, (PetscBool)(!PetscPreLoadMax || PetscPreLoadIt))); \
694     PetscCall(PetscLogStagePush(_stageNum)); \
695   } while (0)
696 
697 /* some vars for logging */
698 PETSC_EXTERN PetscBool PetscPreLoadingUsed; /* true if we are or have done preloading */
699 PETSC_EXTERN PetscBool PetscPreLoadingOn;   /* true if we are currently in a preloading calculation */
700 
701 #if defined(PETSC_USE_LOG) && defined(PETSC_HAVE_DEVICE)
702 
703 /* Global GPU counters */
704 PETSC_EXTERN PetscLogDouble petsc_ctog_ct;
705 PETSC_EXTERN PetscLogDouble petsc_gtoc_ct;
706 PETSC_EXTERN PetscLogDouble petsc_ctog_sz;
707 PETSC_EXTERN PetscLogDouble petsc_gtoc_sz;
708 PETSC_EXTERN PetscLogDouble petsc_ctog_ct_scalar;
709 PETSC_EXTERN PetscLogDouble petsc_gtoc_ct_scalar;
710 PETSC_EXTERN PetscLogDouble petsc_ctog_sz_scalar;
711 PETSC_EXTERN PetscLogDouble petsc_gtoc_sz_scalar;
712 PETSC_EXTERN PetscLogDouble petsc_gflops;
713 PETSC_EXTERN PetscLogDouble petsc_gtime;
714 
715 /* Thread local storage */
716 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_ct_th;
717 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_ct_th;
718 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_sz_th;
719 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_sz_th;
720 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_ct_scalar_th;
721 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_ct_scalar_th;
722 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_sz_scalar_th;
723 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_sz_scalar_th;
724 PETSC_EXTERN_TLS PetscLogDouble petsc_gflops_th;
725 PETSC_EXTERN_TLS PetscLogDouble petsc_gtime_th;
726 
727 PETSC_EXTERN PetscErrorCode PetscLogGpuTime(void);
728 PETSC_EXTERN PetscErrorCode PetscLogGpuTimeBegin(void);
729 PETSC_EXTERN PetscErrorCode PetscLogGpuTimeEnd(void);
730 
731 /*@C
732        PetscLogGpuFlops - Log how many flops are performed in a calculation on the device
733 
734    Input Parameter:
735 .   flops - the number of flops
736 
737    Level: intermediate
738 
739    Notes:
740      To limit the chance of integer overflow when multiplying by a constant, represent the constant as a double,
741      not an integer. Use `PetscLogFlops`(4.0*n) not `PetscLogFlops`(4*n)
742 
743      The values are also added to the total flop count for the MPI rank that is set with `PetscLogFlops()`; hence the number of flops
744      just on the CPU would be the value from set from `PetscLogFlops()` minus the value set from `PetscLogGpuFlops()`
745 
746 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogFlops()`, `PetscLogGpuTimeBegin()`, `PetscLogGpuTimeEnd()`
747 @*/
748 static inline PetscErrorCode PetscLogGpuFlops(PetscLogDouble n)
749 {
750   PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot log negative flops");
751   PetscCall(PetscAddLogDouble(&petsc_TotalFlops, &petsc_TotalFlops_th, PETSC_FLOPS_PER_OP * n));
752   PetscCall(PetscAddLogDouble(&petsc_gflops, &petsc_gflops_th, PETSC_FLOPS_PER_OP * n));
753   return PETSC_SUCCESS;
754 }
755 
756 static inline PetscErrorCode PetscLogGpuTimeAdd(PetscLogDouble t)
757 {
758   return PetscAddLogDouble(&petsc_gtime, &petsc_gtime_th, t);
759 }
760 
761 static inline PetscErrorCode PetscLogCpuToGpu(PetscLogDouble size)
762 {
763   return PetscAddLogDoubleCnt(&petsc_ctog_ct, &petsc_ctog_sz, &petsc_ctog_ct_th, &petsc_ctog_sz_th, size);
764 }
765 
766 static inline PetscErrorCode PetscLogGpuToCpu(PetscLogDouble size)
767 {
768   return PetscAddLogDoubleCnt(&petsc_gtoc_ct, &petsc_gtoc_sz, &petsc_gtoc_ct_th, &petsc_gtoc_sz_th, size);
769 }
770 
771 static inline PetscErrorCode PetscLogCpuToGpuScalar(PetscLogDouble size)
772 {
773   return PetscAddLogDoubleCnt(&petsc_ctog_ct_scalar, &petsc_ctog_sz_scalar, &petsc_ctog_ct_scalar_th, &petsc_ctog_sz_scalar_th, size);
774 }
775 
776 static inline PetscErrorCode PetscLogGpuToCpuScalar(PetscLogDouble size)
777 {
778   return PetscAddLogDoubleCnt(&petsc_gtoc_ct_scalar, &petsc_gtoc_sz_scalar, &petsc_gtoc_ct_scalar_th, &petsc_gtoc_sz_scalar_th, size);
779 }
780 #else
781 
782   #define PetscLogCpuToGpu(a)       PETSC_SUCCESS
783   #define PetscLogGpuToCpu(a)       PETSC_SUCCESS
784   #define PetscLogCpuToGpuScalar(a) PETSC_SUCCESS
785   #define PetscLogGpuToCpuScalar(a) PETSC_SUCCESS
786   #define PetscLogGpuFlops(a)       PETSC_SUCCESS
787   #define PetscLogGpuTime()         PETSC_SUCCESS
788   #define PetscLogGpuTimeAdd(a)     PETSC_SUCCESS
789   #define PetscLogGpuTimeBegin()    PETSC_SUCCESS
790   #define PetscLogGpuTimeEnd()      PETSC_SUCCESS
791 
792 #endif /* PETSC_USE_LOG && PETSC_HAVE_DEVICE */
793 
794 /* remove TLS defines */
795 #undef PETSC_EXTERN_TLS
796 #undef PETSC_TLS
797 
798 #endif
799