xref: /petsc/include/petsclog.h (revision 53e0a2f3e059226debbf8ccad6ed8e4b3449b8a7)
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 
268 PETSC_DEPRECATED_FUNCTION(3, 18, 0, "PetscLogObjectMemory()", ) static inline PetscErrorCode PetscLogObjectMemory(PetscObject o, PetscLogDouble m)
269 {
270   (void)o;
271   (void)m;
272   return PETSC_SUCCESS;
273 }
274 
275 #if defined(PETSC_USE_LOG) /* --- Logging is turned on --------------------------------*/
276 PETSC_EXTERN PetscStageLog  petsc_stageLog;
277 PETSC_EXTERN PetscErrorCode PetscLogGetStageLog(PetscStageLog *);
278 PETSC_EXTERN PetscErrorCode PetscStageLogGetCurrent(PetscStageLog, int *);
279 PETSC_EXTERN PetscErrorCode PetscStageLogGetEventPerfLog(PetscStageLog, int, PetscEventPerfLog *);
280 
281 PETSC_EXTERN PetscErrorCode PetscGetFlops(PetscLogDouble *);
282 
283   #if defined(PETSC_HAVE_MPE)
284 PETSC_EXTERN PetscErrorCode PetscLogMPEBegin(void);
285 PETSC_EXTERN PetscErrorCode PetscLogMPEDump(const char[]);
286   #endif
287 
288 PETSC_EXTERN PetscErrorCode (*PetscLogPLB)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject);
289 PETSC_EXTERN PetscErrorCode (*PetscLogPLE)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject);
290 PETSC_EXTERN PetscErrorCode (*PetscLogPHC)(PetscObject);
291 PETSC_EXTERN PetscErrorCode (*PetscLogPHD)(PetscObject);
292 
293   #define PetscLogObjectParents(p, n, d) PetscMacroReturnStandard(for (int _i = 0; _i < (n); ++_i) PetscCall(PetscLogObjectParent((PetscObject)(p), (PetscObject)(d)[_i]));)
294   #define PetscLogObjectCreate(h)        ((PetscLogPHC) ? (*PetscLogPHC)((PetscObject)(h)) : PETSC_SUCCESS)
295   #define PetscLogObjectDestroy(h)       ((PetscLogPHD) ? (*PetscLogPHD)((PetscObject)(h)) : PETSC_SUCCESS)
296 PETSC_EXTERN PetscErrorCode PetscLogObjectState(PetscObject, const char[], ...) PETSC_ATTRIBUTE_FORMAT(2, 3);
297 
298 /* Initialization functions */
299 PETSC_EXTERN PetscErrorCode PetscLogDefaultBegin(void);
300 PETSC_EXTERN PetscErrorCode PetscLogAllBegin(void);
301 PETSC_EXTERN PetscErrorCode PetscLogNestedBegin(void);
302 PETSC_EXTERN PetscErrorCode PetscLogTraceBegin(FILE *);
303 PETSC_EXTERN PetscErrorCode PetscLogActions(PetscBool);
304 PETSC_EXTERN PetscErrorCode PetscLogObjects(PetscBool);
305 PETSC_EXTERN PetscErrorCode PetscLogSetThreshold(PetscLogDouble, PetscLogDouble *);
306 PETSC_EXTERN PetscErrorCode PetscLogSet(PetscErrorCode (*)(int, int, PetscObject, PetscObject, PetscObject, PetscObject), PetscErrorCode (*)(int, int, PetscObject, PetscObject, PetscObject, PetscObject));
307 
308 /* Output functions */
309 PETSC_EXTERN PetscErrorCode PetscLogView(PetscViewer);
310 PETSC_EXTERN PetscErrorCode PetscLogViewFromOptions(void);
311 PETSC_EXTERN PetscErrorCode PetscLogDump(const char[]);
312 
313 PETSC_EXTERN PetscLogState  petsc_log_state;
314 PETSC_EXTERN PetscErrorCode PetscLogGetState(PetscLogState *);
315   #define PETSC_LOG_HANDLER_MAX 4
316 PETSC_EXTERN PetscLogHandlerHot PetscLogHandlers[PETSC_LOG_HANDLER_MAX];
317 PETSC_EXTERN PetscErrorCode     PetscLogHandlerStart(PetscLogHandler);
318 PETSC_EXTERN PetscErrorCode     PetscLogHandlerStop(PetscLogHandler);
319 PETSC_EXTERN PetscErrorCode     PetscLogPerfstubsBegin(void);
320 PETSC_EXTERN PetscErrorCode PetscLogLegacyCallbacksBegin(PetscErrorCode (*)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject), PetscErrorCode (*)(PetscLogEvent, int, PetscObject, PetscObject, PetscObject, PetscObject), PetscErrorCode (*)(PetscObject), PetscErrorCode (*)(PetscObject));
321 
322 /* Status checking functions */
323 PETSC_EXTERN PetscErrorCode PetscLogIsActive(PetscBool *);
324 
325 /* Stage functions */
326 PETSC_EXTERN PetscErrorCode PetscLogStageRegister(const char[], PetscLogStage *);
327 PETSC_EXTERN PetscErrorCode PetscLogStagePush(PetscLogStage);
328 PETSC_EXTERN PetscErrorCode PetscLogStagePop(void);
329 PETSC_EXTERN PetscErrorCode PetscLogStageSetActive(PetscLogStage, PetscBool);
330 PETSC_EXTERN PetscErrorCode PetscLogStageGetActive(PetscLogStage, PetscBool *);
331 PETSC_EXTERN PetscErrorCode PetscLogStageSetVisible(PetscLogStage, PetscBool);
332 PETSC_EXTERN PetscErrorCode PetscLogStageGetVisible(PetscLogStage, PetscBool *);
333 PETSC_EXTERN PetscErrorCode PetscLogStageGetId(const char[], PetscLogStage *);
334 PETSC_EXTERN PetscErrorCode PetscLogStageGetName(PetscLogEvent, const char **);
335 
336 /* Event functions */
337 PETSC_EXTERN PetscErrorCode PetscLogEventRegister(const char[], PetscClassId, PetscLogEvent *);
338 PETSC_EXTERN PetscErrorCode PetscLogEventSetCollective(PetscLogEvent, PetscBool);
339 PETSC_EXTERN PetscErrorCode PetscLogEventIncludeClass(PetscClassId);
340 PETSC_EXTERN PetscErrorCode PetscLogEventExcludeClass(PetscClassId);
341 PETSC_EXTERN PetscErrorCode PetscLogEventActivate(PetscLogEvent);
342 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivate(PetscLogEvent);
343 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivatePush(PetscLogEvent);
344 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivatePop(PetscLogEvent);
345 PETSC_EXTERN PetscErrorCode PetscLogEventSetActiveAll(PetscLogEvent, PetscBool);
346 PETSC_EXTERN PetscErrorCode PetscLogEventActivateClass(PetscClassId);
347 PETSC_EXTERN PetscErrorCode PetscLogEventDeactivateClass(PetscClassId);
348 PETSC_EXTERN PetscErrorCode PetscLogEventGetId(const char[], PetscLogEvent *);
349 PETSC_EXTERN PetscErrorCode PetscLogEventGetName(PetscLogEvent, const char **);
350 PETSC_EXTERN PetscErrorCode PetscLogEventGetPerfInfo(PetscLogStage, PetscLogEvent, PetscEventPerfInfo *);
351 PETSC_EXTERN PetscErrorCode PetscLogEventSetDof(PetscLogEvent, PetscInt, PetscLogDouble);
352 PETSC_EXTERN PetscErrorCode PetscLogEventSetError(PetscLogEvent, PetscInt, PetscLogDouble);
353 PETSC_EXTERN PetscErrorCode PetscLogPushCurrentEvent_Internal(PetscLogEvent);
354 PETSC_EXTERN PetscErrorCode PetscLogPopCurrentEvent_Internal(void);
355 PETSC_EXTERN PetscErrorCode PetscLogEventsPause(void);
356 PETSC_EXTERN PetscErrorCode PetscLogEventsResume(void);
357 
358 /* Class functions */
359 PETSC_EXTERN PetscErrorCode PetscLogClassGetClassId(const char[], PetscClassId *);
360 PETSC_EXTERN PetscErrorCode PetscLogClassIdGetName(PetscClassId, const char **);
361 
362 PETSC_EXTERN PetscBool PetscLogMemory;
363 
364 PETSC_EXTERN PetscBool      PetscLogSyncOn; /* true if logging synchronization is enabled */
365 PETSC_EXTERN PetscErrorCode PetscLogEventSynchronize(PetscLogEvent, MPI_Comm);
366 
367   #define PetscLogEventSync(e, comm) \
368     ((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)))
369 
370   #define PetscLogEventBegin(e, o1, o2, o3, o4) \
371     ((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))
372 
373   #define PetscLogEventEnd(e, o1, o2, o3, o4) \
374     ((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))
375 
376 PETSC_EXTERN PetscErrorCode PetscLogEventGetFlops(PetscLogEvent, PetscLogDouble *);
377 PETSC_EXTERN PetscErrorCode PetscLogEventZeroFlops(PetscLogEvent);
378 
379 /* Global flop counter */
380 PETSC_EXTERN PetscLogDouble petsc_TotalFlops;
381 PETSC_EXTERN PetscLogDouble petsc_irecv_ct;
382 PETSC_EXTERN PetscLogDouble petsc_isend_ct;
383 PETSC_EXTERN PetscLogDouble petsc_recv_ct;
384 PETSC_EXTERN PetscLogDouble petsc_send_ct;
385 PETSC_EXTERN PetscLogDouble petsc_irecv_len;
386 PETSC_EXTERN PetscLogDouble petsc_isend_len;
387 PETSC_EXTERN PetscLogDouble petsc_recv_len;
388 PETSC_EXTERN PetscLogDouble petsc_send_len;
389 PETSC_EXTERN PetscLogDouble petsc_allreduce_ct;
390 PETSC_EXTERN PetscLogDouble petsc_gather_ct;
391 PETSC_EXTERN PetscLogDouble petsc_scatter_ct;
392 PETSC_EXTERN PetscLogDouble petsc_wait_ct;
393 PETSC_EXTERN PetscLogDouble petsc_wait_any_ct;
394 PETSC_EXTERN PetscLogDouble petsc_wait_all_ct;
395 PETSC_EXTERN PetscLogDouble petsc_sum_of_waits_ct;
396 
397 /* Thread local storage */
398 PETSC_EXTERN_TLS PetscLogDouble petsc_TotalFlops_th;
399 PETSC_EXTERN_TLS PetscLogDouble petsc_irecv_ct_th;
400 PETSC_EXTERN_TLS PetscLogDouble petsc_isend_ct_th;
401 PETSC_EXTERN_TLS PetscLogDouble petsc_recv_ct_th;
402 PETSC_EXTERN_TLS PetscLogDouble petsc_send_ct_th;
403 PETSC_EXTERN_TLS PetscLogDouble petsc_irecv_len_th;
404 PETSC_EXTERN_TLS PetscLogDouble petsc_isend_len_th;
405 PETSC_EXTERN_TLS PetscLogDouble petsc_recv_len_th;
406 PETSC_EXTERN_TLS PetscLogDouble petsc_send_len_th;
407 PETSC_EXTERN_TLS PetscLogDouble petsc_allreduce_ct_th;
408 PETSC_EXTERN_TLS PetscLogDouble petsc_gather_ct_th;
409 PETSC_EXTERN_TLS PetscLogDouble petsc_scatter_ct_th;
410 PETSC_EXTERN_TLS PetscLogDouble petsc_wait_ct_th;
411 PETSC_EXTERN_TLS PetscLogDouble petsc_wait_any_ct_th;
412 PETSC_EXTERN_TLS PetscLogDouble petsc_wait_all_ct_th;
413 PETSC_EXTERN_TLS PetscLogDouble petsc_sum_of_waits_ct_th;
414 
415   /*
416    Flop counting:  We count each arithmetic operation (e.g., addition, multiplication) separately.
417 
418    For the complex numbers version, note that
419        1 complex addition = 2 flops
420        1 complex multiplication = 6 flops,
421    where we define 1 flop as that for a double precision scalar.  We roughly approximate
422    flop counting for complex numbers by multiplying the total flops by 4; this corresponds
423    to the assumption that we're counting mostly additions and multiplications -- and
424    roughly the same number of each.  More accurate counting could be done by distinguishing
425    among the various arithmetic operations.
426  */
427 
428   #if defined(PETSC_USE_COMPLEX)
429     #define PETSC_FLOPS_PER_OP 4.0
430   #else
431     #define PETSC_FLOPS_PER_OP 1.0
432   #endif
433 
434 /*@C
435        PetscLogFlops - Log how many flops are performed in a calculation
436 
437    Input Parameter:
438 .   flops - the number of flops
439 
440    Level: intermediate
441 
442    Note:
443      To limit the chance of integer overflow when multiplying by a constant, represent the constant as a double,
444      not an integer. Use `PetscLogFlops`(4.0*n) not `PetscLogFlops`(4*n)
445 
446 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogGpuFlops()`
447 @*/
448 static inline PetscErrorCode PetscLogFlops(PetscLogDouble n)
449 {
450   PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot log negative flops");
451   return PetscAddLogDouble(&petsc_TotalFlops, &petsc_TotalFlops_th, PETSC_FLOPS_PER_OP * n);
452 }
453 
454   /*
455      These are used internally in the PETSc routines to keep a count of MPI messages and
456    their sizes.
457 
458      This does not work for MPI-Uni because our include/petsc/mpiuni/mpi.h file
459    uses macros to defined the MPI operations.
460 
461      It does not work correctly from HP-UX because it processes the
462    macros in a way that sometimes it double counts, hence
463    PETSC_HAVE_BROKEN_RECURSIVE_MACRO
464 
465      It does not work with Windows because winmpich lacks MPI_Type_size()
466 */
467   #if !defined(MPIUNI_H) && !defined(PETSC_HAVE_BROKEN_RECURSIVE_MACRO)
468 /*
469    Logging of MPI activities
470 */
471 static inline PetscErrorCode PetscMPITypeSize(PetscInt count, MPI_Datatype type, PetscLogDouble *length, PetscLogDouble *length_th)
472 {
473   PetscMPIInt typesize;
474 
475   if (type == MPI_DATATYPE_NULL) return PETSC_SUCCESS;
476   PetscCallMPI(MPI_Type_size(type, &typesize));
477   return PetscAddLogDouble(length, length_th, (PetscLogDouble)(count * typesize));
478 }
479 
480 static inline PetscErrorCode PetscMPITypeSizeComm(MPI_Comm comm, const PetscMPIInt *counts, MPI_Datatype type, PetscLogDouble *length, PetscLogDouble *length_th)
481 {
482   PetscMPIInt    typesize, size, p;
483   PetscLogDouble l;
484 
485   if (type == MPI_DATATYPE_NULL) return PETSC_SUCCESS;
486   PetscCallMPI(MPI_Comm_size(comm, &size));
487   PetscCallMPI(MPI_Type_size(type, &typesize));
488   for (p = 0, l = 0.0; p < size; ++p) l += (PetscLogDouble)(counts[p] * typesize);
489   return PetscAddLogDouble(length, length_th, l);
490 }
491 
492 /*
493     Returns 1 if the communicator is parallel else zero
494 */
495 static inline int PetscMPIParallelComm(MPI_Comm comm)
496 {
497   PetscMPIInt size;
498   MPI_Comm_size(comm, &size);
499   return size > 1;
500 }
501 
502     #define MPI_Irecv(buf, count, datatype, source, tag, comm, request) \
503       (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)))
504 
505     #define MPI_Irecv_c(buf, count, datatype, source, tag, comm, request) \
506       (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)))
507 
508     #define MPI_Isend(buf, count, datatype, dest, tag, comm, request) \
509       (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)))
510 
511     #define MPI_Isend_c(buf, count, datatype, dest, tag, comm, request) \
512       (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)))
513 
514     #define MPI_Startall_irecv(count, datatype, number, requests) \
515       (PetscAddLogDouble(&petsc_irecv_ct, &petsc_irecv_ct_th, number) || PetscMPITypeSize((count), (datatype), &(petsc_irecv_len), &(petsc_irecv_len_th)) || ((number) && MPI_Startall((number), (requests))))
516 
517     #define MPI_Startall_isend(count, datatype, number, requests) \
518       (PetscAddLogDouble(&petsc_isend_ct, &petsc_isend_ct_th, number) || PetscMPITypeSize((count), (datatype), &(petsc_isend_len), &(petsc_isend_len_th)) || ((number) && MPI_Startall((number), (requests))))
519 
520     #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)))
521 
522     #define MPI_Recv(buf, count, datatype, source, tag, comm, status) \
523       (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)))
524 
525     #define MPI_Recv_c(buf, count, datatype, source, tag, comm, status) \
526       (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)))
527 
528     #define MPI_Send(buf, count, datatype, dest, tag, comm) \
529       (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)))
530 
531     #define MPI_Send_c(buf, count, datatype, dest, tag, comm) \
532       (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)))
533 
534     #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)))
535 
536     #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)))
537 
538     #define MPI_Waitall(count, array_of_requests, array_of_statuses) \
539       (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)))
540 
541     #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)))
542 
543     #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)))
544 
545     #define MPI_Reduce_scatter_block(sendbuf, recvbuf, recvcount, datatype, op, comm) \
546       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || MPI_Reduce_scatter_block((sendbuf), (recvbuf), (recvcount), (datatype), (op), (comm)))
547 
548     #define MPI_Alltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm) \
549       (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)))
550 
551     #define MPI_Alltoallv(sendbuf, sendcnts, sdispls, sendtype, recvbuf, recvcnts, rdispls, recvtype, comm) \
552       (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)))
553 
554     #define MPI_Allgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm) \
555       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Allgather((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (comm)))
556 
557     #define MPI_Allgatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, comm) \
558       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Allgatherv((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (displs), (recvtype), (comm)))
559 
560     #define MPI_Gather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm) \
561       (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)))
562 
563     #define MPI_Gatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, root, comm) \
564       (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)))
565 
566     #define MPI_Scatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm) \
567       (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)))
568 
569     #define MPI_Scatterv(sendbuf, sendcount, displs, sendtype, recvbuf, recvcount, recvtype, root, comm) \
570       (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)))
571 
572     #define MPI_Ialltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm, request) \
573       (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)))
574 
575     #define MPI_Ialltoallv(sendbuf, sendcnts, sdispls, sendtype, recvbuf, recvcnts, rdispls, recvtype, comm, request) \
576       (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)))
577 
578     #define MPI_Iallgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm, request) \
579       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Iallgather((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (recvtype), (comm), (request)))
580 
581     #define MPI_Iallgatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, comm, request) \
582       (PetscAddLogDouble(&petsc_gather_ct, &petsc_gather_ct_th, PetscMPIParallelComm(comm)) || MPI_Iallgatherv((sendbuf), (sendcount), (sendtype), (recvbuf), (recvcount), (displs), (recvtype), (comm), (request)))
583 
584     #define MPI_Igather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm, request) \
585       (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)))
586 
587     #define MPI_Igatherv(sendbuf, sendcount, sendtype, recvbuf, recvcount, displs, recvtype, root, comm, request) \
588       (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)))
589 
590     #define MPI_Iscatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm, request) \
591       (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)))
592 
593     #define MPI_Iscatterv(sendbuf, sendcount, displs, sendtype, recvbuf, recvcount, recvtype, root, comm, request) \
594       (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)))
595 
596     #define MPIX_Send_enqueue(buf, count, datatype, dest, tag, comm) \
597       (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)))
598 
599     #define MPIX_Recv_enqueue(buf, count, datatype, source, tag, comm, status) \
600       (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)))
601 
602     #define MPIX_Isend_enqueue(buf, count, datatype, dest, tag, comm, request) \
603       (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)))
604 
605     #define MPIX_Irecv_enqueue(buf, count, datatype, source, tag, comm, request) \
606       (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)))
607 
608     #define MPIX_Allreduce_enqueue(sendbuf, recvbuf, count, datatype, op, comm) \
609       (PetscAddLogDouble(&petsc_allreduce_ct, &petsc_allreduce_ct_th, PetscMPIParallelComm(comm)) || MPIX_Allreduce_enqueue((sendbuf), (recvbuf), (count), (datatype), (op), (comm)))
610 
611     #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)))
612 
613     #define MPIX_Waitall_enqueue(count, array_of_requests, array_of_statuses) \
614       (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)))
615   #else
616 
617     #define MPI_Startall_irecv(count, datatype, number, requests) ((number) && MPI_Startall((number), (requests)))
618 
619     #define MPI_Startall_isend(count, datatype, number, requests) ((number) && MPI_Startall((number), (requests)))
620 
621     #define MPI_Start_isend(count, datatype, requests) (MPI_Start((requests)))
622 
623   #endif /* !MPIUNI_H && ! PETSC_HAVE_BROKEN_RECURSIVE_MACRO */
624 
625 #else /* ---Logging is turned off --------------------------------------------*/
626 
627   #define PetscLogMemory PETSC_FALSE
628 
629   #define PetscLogGetState(a)     (*(a) = NULL, PETSC_SUCCESS)
630   #define PetscLogHandlerStart(a) ((void)(a), PETSC_SUCCESS)
631   #define PetscLogHandlerStop(a)  ((void)(a), PETSC_SUCCESS)
632 
633   #define PetscLogFlops(n) ((void)(n), PETSC_SUCCESS)
634   #define PetscGetFlops(a) (*(a) = 0.0, PETSC_SUCCESS)
635 
636   #define PetscLogStageRegister(a, b)   PETSC_SUCCESS
637   #define PetscLogStagePush(a)          PETSC_SUCCESS
638   #define PetscLogStagePop()            PETSC_SUCCESS
639   #define PetscLogStageSetActive(a, b)  PETSC_SUCCESS
640   #define PetscLogStageGetActive(a, b)  PETSC_SUCCESS
641   #define PetscLogStageGetVisible(a, b) PETSC_SUCCESS
642   #define PetscLogStageSetVisible(a, b) PETSC_SUCCESS
643   #define PetscLogStageGetId(a, b)      (*(b) = 0, PETSC_SUCCESS)
644   #define PetscLogStageGetName(a, b)    ((void)(a), *(b) = NULL, PETSC_SUCCESS)
645 
646   #define PetscLogEventRegister(a, b, c)    PETSC_SUCCESS
647   #define PetscLogEventSetCollective(a, b)  PETSC_SUCCESS
648   #define PetscLogEventIncludeClass(a)      PETSC_SUCCESS
649   #define PetscLogEventExcludeClass(a)      PETSC_SUCCESS
650   #define PetscLogEventActivate(a)          PETSC_SUCCESS
651   #define PetscLogEventDeactivate(a)        PETSC_SUCCESS
652   #define PetscLogEventDeactivatePush(a)    PETSC_SUCCESS
653   #define PetscLogEventDeactivatePop(a)     PETSC_SUCCESS
654   #define PetscLogEventActivateClass(a)     PETSC_SUCCESS
655   #define PetscLogEventDeactivateClass(a)   PETSC_SUCCESS
656   #define PetscLogEventSetActiveAll(a, b)   PETSC_SUCCESS
657   #define PetscLogEventGetId(a, b)          (*(b) = 0, PETSC_SUCCESS)
658   #define PetscLogEventGetName(a, b)        ((void)(a), *(b) = NULL, PETSC_SUCCESS)
659   #define PetscLogEventGetPerfInfo(a, b, c) PETSC_SUCCESS
660   #define PetscLogEventSetDof(a, b, c)      PETSC_SUCCESS
661   #define PetscLogEventSetError(a, b, c)    PETSC_SUCCESS
662   #define PetscLogEventsPause()             PETSC_SUCCESS
663   #define PetscLogEventsResume()            PETSC_SUCCESS
664 
665   #define PetscLogClassGetClassId(a, b) (*(b) = -1, PETSC_SUCCESS)
666   #define PetscLogClassIdGetName(a, b)  (*(b) = NULL, PETSC_SUCCESS)
667 
668   #define PetscLogPLB PETSC_SUCCESS
669   #define PetscLogPLE PETSC_SUCCESS
670   #define PetscLogPHC PETSC_SUCCESS
671   #define PetscLogPHD PETSC_SUCCESS
672 
673   #define PetscLogObjectParents(p, n, c) PETSC_SUCCESS
674   #define PetscLogObjectCreate(h)        PETSC_SUCCESS
675   #define PetscLogObjectDestroy(h)       PETSC_SUCCESS
676 PETSC_EXTERN PetscErrorCode PetscLogObjectState(PetscObject, const char[], ...) PETSC_ATTRIBUTE_FORMAT(2, 3);
677 
678   #define PetscLogDefaultBegin()   PETSC_SUCCESS
679   #define PetscLogAllBegin()       PETSC_SUCCESS
680   #define PetscLogNestedBegin()    PETSC_SUCCESS
681   #define PetscLogTraceBegin(file) PETSC_SUCCESS
682 
683   #define PetscLogPerfstubsBegin()                 PETSC_SUCCESS
684   #define PetscLogLegacyCallbacksBegin(a, b, c, d) ((void)(a), (void)(b), (void)(c), (void)(d), PETSC_SUCCESS)
685 
686   #define PetscLogActions(a)         PETSC_SUCCESS
687   #define PetscLogObjects(a)         PETSC_SUCCESS
688   #define PetscLogSetThreshold(a, b) PETSC_SUCCESS
689   #define PetscLogSet(lb, le)        PETSC_SUCCESS
690   #define PetscLogIsActive(flag)     (*(flag) = PETSC_FALSE, PETSC_SUCCESS)
691 
692   #define PetscLogView(viewer)      PETSC_SUCCESS
693   #define PetscLogViewFromOptions() PETSC_SUCCESS
694   #define PetscLogDump(c)           PETSC_SUCCESS
695 
696   #define PetscLogEventSync(e, comm)                            PETSC_SUCCESS
697   #define PetscLogEventBegin(e, o1, o2, o3, o4)                 PETSC_SUCCESS
698   #define PetscLogEventEnd(e, o1, o2, o3, o4)                   PETSC_SUCCESS
699 
700   /* If PETSC_USE_LOG is NOT defined, these still need to be! */
701   #define MPI_Startall_irecv(count, datatype, number, requests) ((number) && MPI_Startall(number, requests))
702   #define MPI_Startall_isend(count, datatype, number, requests) ((number) && MPI_Startall(number, requests))
703   #define MPI_Start_isend(count, datatype, requests)            MPI_Start(requests)
704 
705 #endif /* PETSC_USE_LOG */
706 
707 #define PetscPreLoadBegin(flag, name) \
708   do { \
709     PetscBool     PetscPreLoading = flag; \
710     int           PetscPreLoadMax, PetscPreLoadIt; \
711     PetscLogStage _stageNum; \
712     PetscCall(PetscOptionsGetBool(NULL, NULL, "-preload", &PetscPreLoading, NULL)); \
713     PetscPreLoadMax     = (int)(PetscPreLoading); \
714     PetscPreLoadingUsed = PetscPreLoading ? PETSC_TRUE : PetscPreLoadingUsed; \
715     for (PetscPreLoadIt = 0; PetscPreLoadIt <= PetscPreLoadMax; PetscPreLoadIt++) { \
716       PetscPreLoadingOn = PetscPreLoading; \
717       PetscCall(PetscBarrier(NULL)); \
718       if (PetscPreLoadIt > 0) PetscCall(PetscLogStageGetId(name, &_stageNum)); \
719       else PetscCall(PetscLogStageRegister(name, &_stageNum)); \
720       PetscCall(PetscLogStageSetActive(_stageNum, (PetscBool)(!PetscPreLoadMax || PetscPreLoadIt))); \
721       PetscCall(PetscLogStagePush(_stageNum))
722 
723 #define PetscPreLoadEnd() \
724   PetscCall(PetscLogStagePop()); \
725   PetscPreLoading = PETSC_FALSE; \
726   } \
727   } \
728   while (0)
729 
730 #define PetscPreLoadStage(name) \
731   do { \
732     PetscCall(PetscLogStagePop()); \
733     if (PetscPreLoadIt > 0) PetscCall(PetscLogStageGetId(name, &_stageNum)); \
734     else PetscCall(PetscLogStageRegister(name, &_stageNum)); \
735     PetscCall(PetscLogStageSetActive(_stageNum, (PetscBool)(!PetscPreLoadMax || PetscPreLoadIt))); \
736     PetscCall(PetscLogStagePush(_stageNum)); \
737   } while (0)
738 
739 /* some vars for logging */
740 PETSC_EXTERN PetscBool PetscPreLoadingUsed; /* true if we are or have done preloading */
741 PETSC_EXTERN PetscBool PetscPreLoadingOn;   /* true if we are currently in a preloading calculation */
742 
743 #if defined(PETSC_USE_LOG) && defined(PETSC_HAVE_DEVICE)
744 
745 /* Global GPU counters */
746 PETSC_EXTERN PetscLogDouble petsc_ctog_ct;
747 PETSC_EXTERN PetscLogDouble petsc_gtoc_ct;
748 PETSC_EXTERN PetscLogDouble petsc_ctog_sz;
749 PETSC_EXTERN PetscLogDouble petsc_gtoc_sz;
750 PETSC_EXTERN PetscLogDouble petsc_ctog_ct_scalar;
751 PETSC_EXTERN PetscLogDouble petsc_gtoc_ct_scalar;
752 PETSC_EXTERN PetscLogDouble petsc_ctog_sz_scalar;
753 PETSC_EXTERN PetscLogDouble petsc_gtoc_sz_scalar;
754 PETSC_EXTERN PetscLogDouble petsc_gflops;
755 PETSC_EXTERN PetscLogDouble petsc_gtime;
756 
757 /* Thread local storage */
758 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_ct_th;
759 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_ct_th;
760 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_sz_th;
761 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_sz_th;
762 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_ct_scalar_th;
763 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_ct_scalar_th;
764 PETSC_EXTERN_TLS PetscLogDouble petsc_ctog_sz_scalar_th;
765 PETSC_EXTERN_TLS PetscLogDouble petsc_gtoc_sz_scalar_th;
766 PETSC_EXTERN_TLS PetscLogDouble petsc_gflops_th;
767 PETSC_EXTERN_TLS PetscLogDouble petsc_gtime_th;
768 
769 PETSC_EXTERN PetscErrorCode PetscLogGpuTime(void);
770 PETSC_EXTERN PetscErrorCode PetscLogGpuTimeBegin(void);
771 PETSC_EXTERN PetscErrorCode PetscLogGpuTimeEnd(void);
772 
773 /*@C
774        PetscLogGpuFlops - Log how many flops are performed in a calculation on the device
775 
776    Input Parameter:
777 .   flops - the number of flops
778 
779    Level: intermediate
780 
781    Notes:
782      To limit the chance of integer overflow when multiplying by a constant, represent the constant as a double,
783      not an integer. Use `PetscLogFlops`(4.0*n) not `PetscLogFlops`(4*n)
784 
785      The values are also added to the total flop count for the MPI rank that is set with `PetscLogFlops()`; hence the number of flops
786      just on the CPU would be the value from set from `PetscLogFlops()` minus the value set from `PetscLogGpuFlops()`
787 
788 .seealso: [](ch_profiling), `PetscLogView()`, `PetscLogFlops()`, `PetscLogGpuTimeBegin()`, `PetscLogGpuTimeEnd()`
789 @*/
790 static inline PetscErrorCode PetscLogGpuFlops(PetscLogDouble n)
791 {
792   PetscAssert(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot log negative flops");
793   PetscCall(PetscAddLogDouble(&petsc_TotalFlops, &petsc_TotalFlops_th, PETSC_FLOPS_PER_OP * n));
794   PetscCall(PetscAddLogDouble(&petsc_gflops, &petsc_gflops_th, PETSC_FLOPS_PER_OP * n));
795   return PETSC_SUCCESS;
796 }
797 
798 static inline PetscErrorCode PetscLogGpuTimeAdd(PetscLogDouble t)
799 {
800   return PetscAddLogDouble(&petsc_gtime, &petsc_gtime_th, t);
801 }
802 
803 static inline PetscErrorCode PetscLogCpuToGpu(PetscLogDouble size)
804 {
805   return PetscAddLogDoubleCnt(&petsc_ctog_ct, &petsc_ctog_sz, &petsc_ctog_ct_th, &petsc_ctog_sz_th, size);
806 }
807 
808 static inline PetscErrorCode PetscLogGpuToCpu(PetscLogDouble size)
809 {
810   return PetscAddLogDoubleCnt(&petsc_gtoc_ct, &petsc_gtoc_sz, &petsc_gtoc_ct_th, &petsc_gtoc_sz_th, size);
811 }
812 
813 static inline PetscErrorCode PetscLogCpuToGpuScalar(PetscLogDouble size)
814 {
815   return PetscAddLogDoubleCnt(&petsc_ctog_ct_scalar, &petsc_ctog_sz_scalar, &petsc_ctog_ct_scalar_th, &petsc_ctog_sz_scalar_th, size);
816 }
817 
818 static inline PetscErrorCode PetscLogGpuToCpuScalar(PetscLogDouble size)
819 {
820   return PetscAddLogDoubleCnt(&petsc_gtoc_ct_scalar, &petsc_gtoc_sz_scalar, &petsc_gtoc_ct_scalar_th, &petsc_gtoc_sz_scalar_th, size);
821 }
822 #else
823 
824   #define PetscLogCpuToGpu(a)       PETSC_SUCCESS
825   #define PetscLogGpuToCpu(a)       PETSC_SUCCESS
826   #define PetscLogCpuToGpuScalar(a) PETSC_SUCCESS
827   #define PetscLogGpuToCpuScalar(a) PETSC_SUCCESS
828   #define PetscLogGpuFlops(a)       PETSC_SUCCESS
829   #define PetscLogGpuTime()         PETSC_SUCCESS
830   #define PetscLogGpuTimeAdd(a)     PETSC_SUCCESS
831   #define PetscLogGpuTimeBegin()    PETSC_SUCCESS
832   #define PetscLogGpuTimeEnd()      PETSC_SUCCESS
833 
834 #endif /* PETSC_USE_LOG && PETSC_HAVE_DEVICE */
835 
836 /* remove TLS defines */
837 #undef PETSC_EXTERN_TLS
838 #undef PETSC_TLS
839 
840 #endif
841