1936c8cb4SToby Isaac const char help[] = "How to create a log handler using the PetscLogHandler interface";
2936c8cb4SToby Isaac
3936c8cb4SToby Isaac #include <petscsys.h>
4936c8cb4SToby Isaac #include <petsc/private/hashmapi.h> // use PetscHMapI: a PetscInt -> PetscInt hashmap
5936c8cb4SToby Isaac #include <petsctime.h> // use PetscTimeSubtract() and PetscTimeAdd()
6936c8cb4SToby Isaac #include <petscviewer.h>
7936c8cb4SToby Isaac #include <petsc/private/loghandlerimpl.h> // use the struct _p_PetscLogHandler behind PetscLogHandler
8936c8cb4SToby Isaac
9936c8cb4SToby Isaac /* Log handlers that use the PetscLogHandler interface get their information
10936c8cb4SToby Isaac from the PetscLogState available to each handler and the user-defined
11936c8cb4SToby Isaac context pointer. Compare this example to src/sys/tutorials/ex6.c.
12936c8cb4SToby Isaac
13936c8cb4SToby Isaac A logging event can be started multiple times before it stops: for example,
14936c8cb4SToby Isaac a linear solve may involve a subsolver, so PetscLogEventBegin() can be
15936c8cb4SToby Isaac called for the event KSP_Solve multiple times before a call to
16936c8cb4SToby Isaac PetscLogEventEnd(). The user defined handler in this example shows how many
17936c8cb4SToby Isaac times an event is running. */
18936c8cb4SToby Isaac
19294de794SToby Isaac #define PETSCLOGHANDLEREX7 "ex7"
20936c8cb4SToby Isaac
21936c8cb4SToby Isaac typedef struct _HandlerCtx *HandlerCtx;
22936c8cb4SToby Isaac
23936c8cb4SToby Isaac struct _HandlerCtx {
24936c8cb4SToby Isaac PetscHMapI running;
25936c8cb4SToby Isaac PetscInt num_objects_created;
26936c8cb4SToby Isaac PetscInt num_objects_destroyed;
27936c8cb4SToby Isaac };
28936c8cb4SToby Isaac
HandlerCtxCreate(HandlerCtx * ctx_p)29936c8cb4SToby Isaac static PetscErrorCode HandlerCtxCreate(HandlerCtx *ctx_p)
30936c8cb4SToby Isaac {
31936c8cb4SToby Isaac HandlerCtx ctx;
32936c8cb4SToby Isaac
33936c8cb4SToby Isaac PetscFunctionBegin;
34936c8cb4SToby Isaac PetscCall(PetscNew(ctx_p));
35936c8cb4SToby Isaac ctx = *ctx_p;
36936c8cb4SToby Isaac PetscCall(PetscHMapICreate(&ctx->running));
37936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
38936c8cb4SToby Isaac }
39936c8cb4SToby Isaac
HandlerCtxDestroy(HandlerCtx * ctx_p)40936c8cb4SToby Isaac static PetscErrorCode HandlerCtxDestroy(HandlerCtx *ctx_p)
41936c8cb4SToby Isaac {
42936c8cb4SToby Isaac HandlerCtx ctx;
43936c8cb4SToby Isaac
44936c8cb4SToby Isaac PetscFunctionBegin;
45936c8cb4SToby Isaac ctx = *ctx_p;
46936c8cb4SToby Isaac *ctx_p = NULL;
47936c8cb4SToby Isaac PetscCall(PetscHMapIDestroy(&ctx->running));
48936c8cb4SToby Isaac PetscCall(PetscFree(ctx));
49936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
50936c8cb4SToby Isaac }
51936c8cb4SToby Isaac
52936c8cb4SToby Isaac #define PrintData(format_string, ...) \
53936c8cb4SToby Isaac do { \
54936c8cb4SToby Isaac PetscMPIInt _rank; \
55936c8cb4SToby Isaac PetscLogDouble _time; \
56936c8cb4SToby Isaac PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &_rank)); \
57936c8cb4SToby Isaac PetscCall(PetscTime(&_time)); \
58dff009beSToby Isaac PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d:%-7g:%-33s] " format_string, _rank, _time, PETSC_FUNCTION_NAME, __VA_ARGS__)); \
59936c8cb4SToby Isaac } while (0)
60936c8cb4SToby Isaac
PetscLogHandlerEventBegin_Ex7(PetscLogHandler h,PetscLogEvent e,PetscObject o1,PetscObject o2,PetscObject o3,PetscObject o4)61936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerEventBegin_Ex7(PetscLogHandler h, PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
62936c8cb4SToby Isaac {
63936c8cb4SToby Isaac HandlerCtx ctx;
64936c8cb4SToby Isaac PetscInt count;
65936c8cb4SToby Isaac PetscLogState state;
66936c8cb4SToby Isaac PetscLogEventInfo event_info;
67936c8cb4SToby Isaac PetscBool is_active;
68936c8cb4SToby Isaac
69936c8cb4SToby Isaac PetscFunctionBegin;
70936c8cb4SToby Isaac // This callback will only be invoked if the event is active
71936c8cb4SToby Isaac PetscCall(PetscLogHandlerGetState(h, &state));
72936c8cb4SToby Isaac PetscCall(PetscLogStateEventGetActive(state, PETSC_DEFAULT, e, &is_active));
73936c8cb4SToby Isaac PetscAssert(is_active, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Event handler called for inactive event");
74936c8cb4SToby Isaac
75936c8cb4SToby Isaac ctx = (HandlerCtx)h->data;
76*300f1712SStefano Zampini PetscCall(PetscHMapIGetWithDefault(ctx->running, e, 0, &count));
77936c8cb4SToby Isaac count += 1;
78936c8cb4SToby Isaac PetscCall(PetscLogStateEventGetInfo(state, e, &event_info));
79936c8cb4SToby Isaac PrintData("Event \"%s\" started: now running %" PetscInt_FMT " times\n", event_info.name, count);
80*300f1712SStefano Zampini PetscCall(PetscHMapISet(ctx->running, e, count));
81936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
82936c8cb4SToby Isaac }
83936c8cb4SToby Isaac
PetscLogHandlerEventEnd_Ex7(PetscLogHandler h,PetscLogEvent e,PetscObject o1,PetscObject o2,PetscObject o3,PetscObject o4)84936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerEventEnd_Ex7(PetscLogHandler h, PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
85936c8cb4SToby Isaac {
86936c8cb4SToby Isaac HandlerCtx ctx;
87936c8cb4SToby Isaac PetscInt count;
88936c8cb4SToby Isaac PetscLogState state;
89936c8cb4SToby Isaac PetscLogEventInfo event_info;
90936c8cb4SToby Isaac
91936c8cb4SToby Isaac PetscFunctionBegin;
92936c8cb4SToby Isaac ctx = (HandlerCtx)h->data;
93936c8cb4SToby Isaac PetscCall(PetscLogHandlerGetState(h, &state));
94*300f1712SStefano Zampini PetscCall(PetscHMapIGetWithDefault(ctx->running, e, 0, &count));
95936c8cb4SToby Isaac count -= 1;
96936c8cb4SToby Isaac PetscCall(PetscLogStateEventGetInfo(state, e, &event_info));
97936c8cb4SToby Isaac PrintData("Event \"%s\" stopped: now running %" PetscInt_FMT " times\n", event_info.name, count);
98*300f1712SStefano Zampini PetscCall(PetscHMapISet(ctx->running, e, count));
99936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
100936c8cb4SToby Isaac }
101936c8cb4SToby Isaac
PetscLogHandlerEventSync_Ex7(PetscLogHandler h,PetscLogEvent e,MPI_Comm comm)102936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerEventSync_Ex7(PetscLogHandler h, PetscLogEvent e, MPI_Comm comm)
103936c8cb4SToby Isaac {
104936c8cb4SToby Isaac PetscLogState state;
105936c8cb4SToby Isaac PetscLogEventInfo event_info;
106936c8cb4SToby Isaac PetscLogDouble time = 0.0;
107936c8cb4SToby Isaac
108936c8cb4SToby Isaac PetscFunctionBegin;
109936c8cb4SToby Isaac PetscCall(PetscTimeSubtract(&time));
110936c8cb4SToby Isaac PetscCallMPI(MPI_Barrier(comm));
111936c8cb4SToby Isaac PetscCall(PetscTimeAdd(&time));
112936c8cb4SToby Isaac PetscCall(PetscLogHandlerGetState(h, &state));
113936c8cb4SToby Isaac PetscCall(PetscLogStateEventGetInfo(state, e, &event_info));
114*300f1712SStefano Zampini PrintData("Event \"%s\" synced: took %g seconds\n", event_info.name, time);
115936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
116936c8cb4SToby Isaac }
117936c8cb4SToby Isaac
PetscLogHandlerObjectCreate_Ex7(PetscLogHandler h,PetscObject obj)118936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerObjectCreate_Ex7(PetscLogHandler h, PetscObject obj)
119936c8cb4SToby Isaac {
120936c8cb4SToby Isaac HandlerCtx ctx;
121936c8cb4SToby Isaac
122936c8cb4SToby Isaac PetscFunctionBegin;
123936c8cb4SToby Isaac ctx = (HandlerCtx)h->data;
124936c8cb4SToby Isaac ctx->num_objects_created++;
125936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
126936c8cb4SToby Isaac }
127936c8cb4SToby Isaac
PetscLogHandlerObjectDestroy_Ex7(PetscLogHandler h,PetscObject obj)128936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerObjectDestroy_Ex7(PetscLogHandler h, PetscObject obj)
129936c8cb4SToby Isaac {
130936c8cb4SToby Isaac HandlerCtx ctx;
131936c8cb4SToby Isaac
132936c8cb4SToby Isaac PetscFunctionBegin;
133936c8cb4SToby Isaac ctx = (HandlerCtx)h->data;
134936c8cb4SToby Isaac ctx->num_objects_destroyed++;
135936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
136936c8cb4SToby Isaac }
137936c8cb4SToby Isaac
PetscLogHandlerStagePush_Ex7(PetscLogHandler h,PetscLogStage new_stage)138936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerStagePush_Ex7(PetscLogHandler h, PetscLogStage new_stage)
139936c8cb4SToby Isaac {
140936c8cb4SToby Isaac PetscLogStage old_stage;
141936c8cb4SToby Isaac PetscLogStageInfo new_info;
142936c8cb4SToby Isaac PetscLogState state;
143936c8cb4SToby Isaac
144936c8cb4SToby Isaac PetscFunctionBegin;
145936c8cb4SToby Isaac PetscCall(PetscLogHandlerGetState(h, &state));
146936c8cb4SToby Isaac PetscCall(PetscLogStateStageGetInfo(state, new_stage, &new_info));
147936c8cb4SToby Isaac PetscCall(PetscLogStateGetCurrentStage(state, &old_stage));
148936c8cb4SToby Isaac if (old_stage >= 0) {
149936c8cb4SToby Isaac PetscLogStageInfo old_info;
150936c8cb4SToby Isaac PetscCall(PetscLogStateStageGetInfo(state, old_stage, &old_info));
151936c8cb4SToby Isaac PrintData("Pushing stage stage \"%s\" (replacing \"%s\")\n", new_info.name, old_info.name);
152936c8cb4SToby Isaac } else {
153936c8cb4SToby Isaac PrintData("Pushing initial stage \"%s\"\n", new_info.name);
154936c8cb4SToby Isaac }
155936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
156936c8cb4SToby Isaac }
157936c8cb4SToby Isaac
PetscLogHandlerStagePop_Ex7(PetscLogHandler h,PetscLogStage old_stage)158936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerStagePop_Ex7(PetscLogHandler h, PetscLogStage old_stage)
159936c8cb4SToby Isaac {
160936c8cb4SToby Isaac PetscLogStage new_stage;
161936c8cb4SToby Isaac PetscLogStageInfo old_info;
162936c8cb4SToby Isaac PetscLogState state;
163936c8cb4SToby Isaac
164936c8cb4SToby Isaac PetscFunctionBegin;
165936c8cb4SToby Isaac PetscCall(PetscLogHandlerGetState(h, &state));
166936c8cb4SToby Isaac PetscCall(PetscLogStateStageGetInfo(state, old_stage, &old_info));
167936c8cb4SToby Isaac PetscCall(PetscLogStateGetCurrentStage(state, &new_stage));
168936c8cb4SToby Isaac if (new_stage >= 0) {
169936c8cb4SToby Isaac PetscLogStageInfo new_info;
170936c8cb4SToby Isaac
171936c8cb4SToby Isaac PetscCall(PetscLogStateStageGetInfo(state, new_stage, &new_info));
172936c8cb4SToby Isaac PrintData("Popping stage \"%s\" (back to \"%s\")\n", old_info.name, new_info.name);
173936c8cb4SToby Isaac } else {
174936c8cb4SToby Isaac PrintData("Popping initial stage \"%s\"\n", old_info.name);
175936c8cb4SToby Isaac }
176936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
177936c8cb4SToby Isaac }
178936c8cb4SToby Isaac
PetscLogHandlerView_Ex7(PetscLogHandler h,PetscViewer viewer)179936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerView_Ex7(PetscLogHandler h, PetscViewer viewer)
180936c8cb4SToby Isaac {
181936c8cb4SToby Isaac PetscBool is_ascii;
182936c8cb4SToby Isaac
183936c8cb4SToby Isaac PetscFunctionBegin;
184936c8cb4SToby Isaac PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &is_ascii));
185936c8cb4SToby Isaac if (is_ascii) {
186936c8cb4SToby Isaac HandlerCtx ctx;
187936c8cb4SToby Isaac PetscInt num_entries;
188936c8cb4SToby Isaac
189936c8cb4SToby Isaac ctx = (HandlerCtx)h->data;
190936c8cb4SToby Isaac PetscCall(PetscHMapIGetSize(ctx->running, &num_entries));
191936c8cb4SToby Isaac PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " events were seen by the handler\n", num_entries));
19293a9da4cSDavid Wells PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " object(s) were created and %" PetscInt_FMT " object(s) were destroyed\n", ctx->num_objects_created, ctx->num_objects_destroyed));
193936c8cb4SToby Isaac }
194936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
195936c8cb4SToby Isaac }
196936c8cb4SToby Isaac
197dff009beSToby Isaac // An example of overloading one of the methods defined using PetscObjectComposeFunction()
PetscLogHandlerLogObjectState_Ex7(PetscLogHandler h,PetscObject obj,const char format[],va_list argp)198dff009beSToby Isaac static PetscErrorCode PetscLogHandlerLogObjectState_Ex7(PetscLogHandler h, PetscObject obj, const char format[], va_list argp)
199dff009beSToby Isaac {
200dff009beSToby Isaac const char *name;
201dff009beSToby Isaac
202dff009beSToby Isaac PetscFunctionBegin;
203dff009beSToby Isaac PetscCall(PetscObjectGetName(obj, &name));
204dff009beSToby Isaac PrintData("Logged state for \"%s\": ", name);
205dff009beSToby Isaac PetscCall(PetscVFPrintf(PETSC_STDOUT, format, argp));
206dff009beSToby Isaac PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
207dff009beSToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
208dff009beSToby Isaac }
209dff009beSToby Isaac
PetscLogHandlerDestroy_Ex7(PetscLogHandler h)210dff009beSToby Isaac static PetscErrorCode PetscLogHandlerDestroy_Ex7(PetscLogHandler h)
211dff009beSToby Isaac {
212dff009beSToby Isaac HandlerCtx ctx;
213dff009beSToby Isaac
214dff009beSToby Isaac PetscFunctionBegin;
215dff009beSToby Isaac ctx = (HandlerCtx)h->data;
216dff009beSToby Isaac PetscCall(HandlerCtxDestroy(&ctx));
217dff009beSToby Isaac PetscCall(PetscObjectComposeFunction((PetscObject)h, "PetscLogHandlerLogObjectState_C", NULL));
218dff009beSToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
219dff009beSToby Isaac }
220dff009beSToby Isaac
PetscLogHandlerCreate_Ex7(PetscLogHandler handler)221936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerCreate_Ex7(PetscLogHandler handler)
222936c8cb4SToby Isaac {
223936c8cb4SToby Isaac HandlerCtx ctx;
224936c8cb4SToby Isaac
225936c8cb4SToby Isaac PetscFunctionBegin;
226936c8cb4SToby Isaac PetscCall(HandlerCtxCreate(&ctx));
227936c8cb4SToby Isaac handler->data = (void *)ctx;
228936c8cb4SToby Isaac handler->ops->destroy = PetscLogHandlerDestroy_Ex7;
229936c8cb4SToby Isaac handler->ops->view = PetscLogHandlerView_Ex7;
230936c8cb4SToby Isaac handler->ops->eventbegin = PetscLogHandlerEventBegin_Ex7;
231936c8cb4SToby Isaac handler->ops->eventend = PetscLogHandlerEventEnd_Ex7;
232936c8cb4SToby Isaac handler->ops->eventsync = PetscLogHandlerEventSync_Ex7;
233936c8cb4SToby Isaac handler->ops->objectcreate = PetscLogHandlerObjectCreate_Ex7;
234936c8cb4SToby Isaac handler->ops->objectdestroy = PetscLogHandlerObjectDestroy_Ex7;
235936c8cb4SToby Isaac handler->ops->stagepush = PetscLogHandlerStagePush_Ex7;
236936c8cb4SToby Isaac handler->ops->stagepop = PetscLogHandlerStagePop_Ex7;
237dff009beSToby Isaac PetscCall(PetscObjectComposeFunction((PetscObject)handler, "PetscLogHandlerLogObjectState_C", PetscLogHandlerLogObjectState_Ex7));
238936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS);
239936c8cb4SToby Isaac }
240936c8cb4SToby Isaac
main(int argc,char ** argv)241936c8cb4SToby Isaac int main(int argc, char **argv)
242936c8cb4SToby Isaac {
243936c8cb4SToby Isaac PetscClassId user_classid;
244936c8cb4SToby Isaac PetscLogEvent event_1, event_2;
245936c8cb4SToby Isaac PetscLogStage stage_1;
246936c8cb4SToby Isaac PetscContainer user_object;
247936c8cb4SToby Isaac PetscLogHandler h;
248dff009beSToby Isaac PetscLogDouble time;
249936c8cb4SToby Isaac PetscLogHandlerType type;
250936c8cb4SToby Isaac
251936c8cb4SToby Isaac PetscCall(PetscInitialize(&argc, &argv, NULL, help));
252294de794SToby Isaac PetscCall(PetscLogHandlerRegister(PETSCLOGHANDLEREX7, PetscLogHandlerCreate_Ex7));
253936c8cb4SToby Isaac
254936c8cb4SToby Isaac PetscCall(PetscLogHandlerCreate(PETSC_COMM_WORLD, &h));
255294de794SToby Isaac PetscCall(PetscLogHandlerSetType(h, PETSCLOGHANDLEREX7));
256936c8cb4SToby Isaac PetscCall(PetscLogHandlerGetType(h, &type));
257936c8cb4SToby Isaac PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Log handler type is: %s\n", type));
258936c8cb4SToby Isaac PetscCall(PetscLogHandlerStart(h));
259936c8cb4SToby Isaac
260936c8cb4SToby Isaac PetscCall(PetscClassIdRegister("User class", &user_classid));
261936c8cb4SToby Isaac PetscCall(PetscLogEventRegister("Event 1", user_classid, &event_1));
262936c8cb4SToby Isaac PetscCall(PetscLogEventRegister("Event 2", user_classid, &event_2));
263936c8cb4SToby Isaac PetscCall(PetscLogStageRegister("Stage 1", &stage_1));
264936c8cb4SToby Isaac
265936c8cb4SToby Isaac PetscCall(PetscLogEventBegin(event_1, NULL, NULL, NULL, NULL));
266936c8cb4SToby Isaac PetscCall(PetscLogStagePush(stage_1));
267936c8cb4SToby Isaac PetscCall(PetscLogEventBegin(event_2, NULL, NULL, NULL, NULL));
268936c8cb4SToby Isaac PetscCall(PetscLogEventSync(event_1, PETSC_COMM_WORLD));
269936c8cb4SToby Isaac PetscCall(PetscLogEventBegin(event_1, NULL, NULL, NULL, NULL));
270dff009beSToby Isaac PetscCall(PetscTime(&time));
271936c8cb4SToby Isaac PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &user_object));
272dff009beSToby Isaac PetscCall(PetscObjectSetName((PetscObject)user_object, "User Container"));
273dff009beSToby Isaac PetscCall(PetscLogHandlerLogObjectState(h, (PetscObject)user_object, "Created at %e", time));
274936c8cb4SToby Isaac PetscCall(PetscContainerDestroy(&user_object));
275936c8cb4SToby Isaac PetscCall(PetscLogEventEnd(event_1, NULL, NULL, NULL, NULL));
276936c8cb4SToby Isaac PetscCall(PetscLogEventEnd(event_2, NULL, NULL, NULL, NULL));
277936c8cb4SToby Isaac PetscCall(PetscLogStagePop());
278936c8cb4SToby Isaac PetscCall(PetscLogEventEnd(event_1, NULL, NULL, NULL, NULL));
279936c8cb4SToby Isaac
280936c8cb4SToby Isaac PetscCall(PetscLogHandlerStop(h));
281936c8cb4SToby Isaac PetscCall(PetscLogHandlerView(h, PETSC_VIEWER_STDOUT_WORLD));
282936c8cb4SToby Isaac PetscCall(PetscLogHandlerDestroy(&h));
283936c8cb4SToby Isaac PetscCall(PetscFinalize());
284936c8cb4SToby Isaac return 0;
285936c8cb4SToby Isaac }
286936c8cb4SToby Isaac
287936c8cb4SToby Isaac /*TEST
288936c8cb4SToby Isaac
289936c8cb4SToby Isaac test:
290936c8cb4SToby Isaac requires: defined(PETSC_USE_LOG)
291936c8cb4SToby Isaac suffix: 0
292936c8cb4SToby Isaac filter: sed -E "s/:[^:]+:/:time_removed:/g"
293936c8cb4SToby Isaac
294936c8cb4SToby Isaac TEST*/
295