xref: /petsc/src/sys/tutorials/ex7.c (revision 936c8cb46dbed228e90bc02ae432d148ebb6df75)
1*936c8cb4SToby Isaac const char help[] = "How to create a log handler using the PetscLogHandler interface";
2*936c8cb4SToby Isaac 
3*936c8cb4SToby Isaac #include <petscsys.h>
4*936c8cb4SToby Isaac #include <petsc/private/hashmapi.h> // use PetscHMapI: a PetscInt -> PetscInt hashmap
5*936c8cb4SToby Isaac #include <petsctime.h>              // use PetscTimeSubtract() and PetscTimeAdd()
6*936c8cb4SToby Isaac #include <petscviewer.h>
7*936c8cb4SToby Isaac #include <petsc/private/loghandlerimpl.h> // use the struct _p_PetscLogHandler behind PetscLogHandler
8*936c8cb4SToby Isaac 
9*936c8cb4SToby Isaac /* Log handlers that use the PetscLogHandler interface get their information
10*936c8cb4SToby Isaac    from the PetscLogState available to each handler and the user-defined
11*936c8cb4SToby Isaac    context pointer.  Compare this example to src/sys/tutorials/ex6.c.
12*936c8cb4SToby Isaac 
13*936c8cb4SToby Isaac    A logging event can be started multiple times before it stops: for example,
14*936c8cb4SToby Isaac    a linear solve may involve a subsolver, so PetscLogEventBegin() can be
15*936c8cb4SToby Isaac    called for the event KSP_Solve multiple times before a call to
16*936c8cb4SToby Isaac    PetscLogEventEnd().  The user defined handler in this example shows how many
17*936c8cb4SToby Isaac    times an event is running. */
18*936c8cb4SToby Isaac 
19*936c8cb4SToby Isaac #define PETSC_LOG_HANDLER_EX7 "ex7"
20*936c8cb4SToby Isaac 
21*936c8cb4SToby Isaac typedef struct _HandlerCtx *HandlerCtx;
22*936c8cb4SToby Isaac 
23*936c8cb4SToby Isaac struct _HandlerCtx {
24*936c8cb4SToby Isaac   PetscHMapI running;
25*936c8cb4SToby Isaac   PetscInt   num_objects_created;
26*936c8cb4SToby Isaac   PetscInt   num_objects_destroyed;
27*936c8cb4SToby Isaac };
28*936c8cb4SToby Isaac 
29*936c8cb4SToby Isaac static PetscErrorCode HandlerCtxCreate(HandlerCtx *ctx_p)
30*936c8cb4SToby Isaac {
31*936c8cb4SToby Isaac   HandlerCtx ctx;
32*936c8cb4SToby Isaac 
33*936c8cb4SToby Isaac   PetscFunctionBegin;
34*936c8cb4SToby Isaac   PetscCall(PetscNew(ctx_p));
35*936c8cb4SToby Isaac   ctx = *ctx_p;
36*936c8cb4SToby Isaac   PetscCall(PetscHMapICreate(&ctx->running));
37*936c8cb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
38*936c8cb4SToby Isaac }
39*936c8cb4SToby Isaac 
40*936c8cb4SToby Isaac static PetscErrorCode HandlerCtxDestroy(HandlerCtx *ctx_p)
41*936c8cb4SToby Isaac {
42*936c8cb4SToby Isaac   HandlerCtx ctx;
43*936c8cb4SToby Isaac 
44*936c8cb4SToby Isaac   PetscFunctionBegin;
45*936c8cb4SToby Isaac   ctx    = *ctx_p;
46*936c8cb4SToby Isaac   *ctx_p = NULL;
47*936c8cb4SToby Isaac   PetscCall(PetscHMapIDestroy(&ctx->running));
48*936c8cb4SToby Isaac   PetscCall(PetscFree(ctx));
49*936c8cb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
50*936c8cb4SToby Isaac }
51*936c8cb4SToby Isaac 
52*936c8cb4SToby Isaac #define PrintData(format_string, ...) \
53*936c8cb4SToby Isaac   do { \
54*936c8cb4SToby Isaac     PetscMPIInt    _rank; \
55*936c8cb4SToby Isaac     PetscLogDouble _time; \
56*936c8cb4SToby Isaac     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &_rank)); \
57*936c8cb4SToby Isaac     PetscCall(PetscTime(&_time)); \
58*936c8cb4SToby Isaac     PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d:%-7g:%-29s] " format_string, _rank, _time, PETSC_FUNCTION_NAME, __VA_ARGS__)); \
59*936c8cb4SToby Isaac   } while (0)
60*936c8cb4SToby Isaac 
61*936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerEventBegin_Ex7(PetscLogHandler h, PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
62*936c8cb4SToby Isaac {
63*936c8cb4SToby Isaac   HandlerCtx        ctx;
64*936c8cb4SToby Isaac   PetscInt          count;
65*936c8cb4SToby Isaac   PetscLogState     state;
66*936c8cb4SToby Isaac   PetscLogEventInfo event_info;
67*936c8cb4SToby Isaac   PetscBool         is_active;
68*936c8cb4SToby Isaac 
69*936c8cb4SToby Isaac   PetscFunctionBegin;
70*936c8cb4SToby Isaac   // This callback will only be invoked if the event is active
71*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerGetState(h, &state));
72*936c8cb4SToby Isaac   PetscCall(PetscLogStateEventGetActive(state, PETSC_DEFAULT, e, &is_active));
73*936c8cb4SToby Isaac   PetscAssert(is_active, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Event handler called for inactive event");
74*936c8cb4SToby Isaac 
75*936c8cb4SToby Isaac   ctx = (HandlerCtx)h->data;
76*936c8cb4SToby Isaac   PetscCall(PetscHMapIGetWithDefault(ctx->running, (PetscInt)e, 0, &count));
77*936c8cb4SToby Isaac   count += 1;
78*936c8cb4SToby Isaac   PetscCall(PetscLogStateEventGetInfo(state, e, &event_info));
79*936c8cb4SToby Isaac   PrintData("Event \"%s\" started: now running %" PetscInt_FMT " times\n", event_info.name, count);
80*936c8cb4SToby Isaac   PetscCall(PetscHMapISet(ctx->running, (PetscInt)e, count));
81*936c8cb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
82*936c8cb4SToby Isaac }
83*936c8cb4SToby Isaac 
84*936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerEventEnd_Ex7(PetscLogHandler h, PetscLogEvent e, PetscObject o1, PetscObject o2, PetscObject o3, PetscObject o4)
85*936c8cb4SToby Isaac {
86*936c8cb4SToby Isaac   HandlerCtx        ctx;
87*936c8cb4SToby Isaac   PetscInt          count;
88*936c8cb4SToby Isaac   PetscLogState     state;
89*936c8cb4SToby Isaac   PetscLogEventInfo event_info;
90*936c8cb4SToby Isaac 
91*936c8cb4SToby Isaac   PetscFunctionBegin;
92*936c8cb4SToby Isaac   ctx = (HandlerCtx)h->data;
93*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerGetState(h, &state));
94*936c8cb4SToby Isaac   PetscCall(PetscHMapIGetWithDefault(ctx->running, (PetscInt)e, 0, &count));
95*936c8cb4SToby Isaac   count -= 1;
96*936c8cb4SToby Isaac   PetscCall(PetscLogStateEventGetInfo(state, e, &event_info));
97*936c8cb4SToby Isaac   PrintData("Event \"%s\" stopped: now running %" PetscInt_FMT " times\n", event_info.name, count);
98*936c8cb4SToby Isaac   PetscCall(PetscHMapISet(ctx->running, (PetscInt)e, count));
99*936c8cb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
100*936c8cb4SToby Isaac }
101*936c8cb4SToby Isaac 
102*936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerEventSync_Ex7(PetscLogHandler h, PetscLogEvent e, MPI_Comm comm)
103*936c8cb4SToby Isaac {
104*936c8cb4SToby Isaac   PetscLogState     state;
105*936c8cb4SToby Isaac   PetscLogEventInfo event_info;
106*936c8cb4SToby Isaac   PetscLogDouble    time = 0.0;
107*936c8cb4SToby Isaac 
108*936c8cb4SToby Isaac   PetscFunctionBegin;
109*936c8cb4SToby Isaac   PetscCall(PetscTimeSubtract(&time));
110*936c8cb4SToby Isaac   PetscCallMPI(MPI_Barrier(comm));
111*936c8cb4SToby Isaac   PetscCall(PetscTimeAdd(&time));
112*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerGetState(h, &state));
113*936c8cb4SToby Isaac   PetscCall(PetscLogStateEventGetInfo(state, e, &event_info));
114*936c8cb4SToby Isaac   PrintData("Event \"%s\" synced: took %g seconds\n", event_info.name, (double)time);
115*936c8cb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
116*936c8cb4SToby Isaac }
117*936c8cb4SToby Isaac 
118*936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerObjectCreate_Ex7(PetscLogHandler h, PetscObject obj)
119*936c8cb4SToby Isaac {
120*936c8cb4SToby Isaac   HandlerCtx ctx;
121*936c8cb4SToby Isaac 
122*936c8cb4SToby Isaac   PetscFunctionBegin;
123*936c8cb4SToby Isaac   ctx = (HandlerCtx)h->data;
124*936c8cb4SToby Isaac   ctx->num_objects_created++;
125*936c8cb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
126*936c8cb4SToby Isaac }
127*936c8cb4SToby Isaac 
128*936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerObjectDestroy_Ex7(PetscLogHandler h, PetscObject obj)
129*936c8cb4SToby Isaac {
130*936c8cb4SToby Isaac   HandlerCtx ctx;
131*936c8cb4SToby Isaac 
132*936c8cb4SToby Isaac   PetscFunctionBegin;
133*936c8cb4SToby Isaac   ctx = (HandlerCtx)h->data;
134*936c8cb4SToby Isaac   ctx->num_objects_destroyed++;
135*936c8cb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
136*936c8cb4SToby Isaac }
137*936c8cb4SToby Isaac 
138*936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerDestroy_Ex7(PetscLogHandler h)
139*936c8cb4SToby Isaac {
140*936c8cb4SToby Isaac   HandlerCtx ctx;
141*936c8cb4SToby Isaac 
142*936c8cb4SToby Isaac   PetscFunctionBegin;
143*936c8cb4SToby Isaac   ctx = (HandlerCtx)h->data;
144*936c8cb4SToby Isaac   PetscCall(HandlerCtxDestroy(&ctx));
145*936c8cb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
146*936c8cb4SToby Isaac }
147*936c8cb4SToby Isaac 
148*936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerStagePush_Ex7(PetscLogHandler h, PetscLogStage new_stage)
149*936c8cb4SToby Isaac {
150*936c8cb4SToby Isaac   PetscLogStage     old_stage;
151*936c8cb4SToby Isaac   PetscLogStageInfo new_info;
152*936c8cb4SToby Isaac   PetscLogState     state;
153*936c8cb4SToby Isaac 
154*936c8cb4SToby Isaac   PetscFunctionBegin;
155*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerGetState(h, &state));
156*936c8cb4SToby Isaac   PetscCall(PetscLogStateStageGetInfo(state, new_stage, &new_info));
157*936c8cb4SToby Isaac   PetscCall(PetscLogStateGetCurrentStage(state, &old_stage));
158*936c8cb4SToby Isaac   if (old_stage >= 0) {
159*936c8cb4SToby Isaac     PetscLogStageInfo old_info;
160*936c8cb4SToby Isaac     PetscCall(PetscLogStateStageGetInfo(state, old_stage, &old_info));
161*936c8cb4SToby Isaac     PrintData("Pushing stage stage \"%s\" (replacing \"%s\")\n", new_info.name, old_info.name);
162*936c8cb4SToby Isaac   } else {
163*936c8cb4SToby Isaac     PrintData("Pushing initial stage \"%s\"\n", new_info.name);
164*936c8cb4SToby Isaac   }
165*936c8cb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
166*936c8cb4SToby Isaac }
167*936c8cb4SToby Isaac 
168*936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerStagePop_Ex7(PetscLogHandler h, PetscLogStage old_stage)
169*936c8cb4SToby Isaac {
170*936c8cb4SToby Isaac   PetscLogStage     new_stage;
171*936c8cb4SToby Isaac   PetscLogStageInfo old_info;
172*936c8cb4SToby Isaac   PetscLogState     state;
173*936c8cb4SToby Isaac 
174*936c8cb4SToby Isaac   PetscFunctionBegin;
175*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerGetState(h, &state));
176*936c8cb4SToby Isaac   PetscCall(PetscLogStateStageGetInfo(state, old_stage, &old_info));
177*936c8cb4SToby Isaac   PetscCall(PetscLogStateGetCurrentStage(state, &new_stage));
178*936c8cb4SToby Isaac   if (new_stage >= 0) {
179*936c8cb4SToby Isaac     PetscLogStageInfo new_info;
180*936c8cb4SToby Isaac 
181*936c8cb4SToby Isaac     PetscCall(PetscLogStateStageGetInfo(state, new_stage, &new_info));
182*936c8cb4SToby Isaac     PrintData("Popping stage \"%s\" (back to \"%s\")\n", old_info.name, new_info.name);
183*936c8cb4SToby Isaac   } else {
184*936c8cb4SToby Isaac     PrintData("Popping initial stage \"%s\"\n", old_info.name);
185*936c8cb4SToby Isaac   }
186*936c8cb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
187*936c8cb4SToby Isaac }
188*936c8cb4SToby Isaac 
189*936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerView_Ex7(PetscLogHandler h, PetscViewer viewer)
190*936c8cb4SToby Isaac {
191*936c8cb4SToby Isaac   PetscBool is_ascii;
192*936c8cb4SToby Isaac 
193*936c8cb4SToby Isaac   PetscFunctionBegin;
194*936c8cb4SToby Isaac   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &is_ascii));
195*936c8cb4SToby Isaac   if (is_ascii) {
196*936c8cb4SToby Isaac     HandlerCtx ctx;
197*936c8cb4SToby Isaac     PetscInt   num_entries;
198*936c8cb4SToby Isaac 
199*936c8cb4SToby Isaac     ctx = (HandlerCtx)h->data;
200*936c8cb4SToby Isaac     PetscCall(PetscHMapIGetSize(ctx->running, &num_entries));
201*936c8cb4SToby Isaac     PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " events were seen by the handler\n", num_entries));
202*936c8cb4SToby Isaac     PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " object(s) were created and %" PetscInt_FMT " object(s) were destroyed\n", ctx->num_objects_created, ctx->num_objects_created));
203*936c8cb4SToby Isaac   }
204*936c8cb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
205*936c8cb4SToby Isaac }
206*936c8cb4SToby Isaac 
207*936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerCreate_Ex7(PetscLogHandler handler)
208*936c8cb4SToby Isaac {
209*936c8cb4SToby Isaac   HandlerCtx ctx;
210*936c8cb4SToby Isaac 
211*936c8cb4SToby Isaac   PetscFunctionBegin;
212*936c8cb4SToby Isaac   PetscCall(HandlerCtxCreate(&ctx));
213*936c8cb4SToby Isaac   handler->data               = (void *)ctx;
214*936c8cb4SToby Isaac   handler->ops->destroy       = PetscLogHandlerDestroy_Ex7;
215*936c8cb4SToby Isaac   handler->ops->view          = PetscLogHandlerView_Ex7;
216*936c8cb4SToby Isaac   handler->ops->eventbegin    = PetscLogHandlerEventBegin_Ex7;
217*936c8cb4SToby Isaac   handler->ops->eventend      = PetscLogHandlerEventEnd_Ex7;
218*936c8cb4SToby Isaac   handler->ops->eventsync     = PetscLogHandlerEventSync_Ex7;
219*936c8cb4SToby Isaac   handler->ops->objectcreate  = PetscLogHandlerObjectCreate_Ex7;
220*936c8cb4SToby Isaac   handler->ops->objectdestroy = PetscLogHandlerObjectDestroy_Ex7;
221*936c8cb4SToby Isaac   handler->ops->stagepush     = PetscLogHandlerStagePush_Ex7;
222*936c8cb4SToby Isaac   handler->ops->stagepop      = PetscLogHandlerStagePop_Ex7;
223*936c8cb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
224*936c8cb4SToby Isaac }
225*936c8cb4SToby Isaac 
226*936c8cb4SToby Isaac int main(int argc, char **argv)
227*936c8cb4SToby Isaac {
228*936c8cb4SToby Isaac   PetscClassId        user_classid;
229*936c8cb4SToby Isaac   PetscLogEvent       event_1, event_2;
230*936c8cb4SToby Isaac   PetscLogStage       stage_1;
231*936c8cb4SToby Isaac   PetscContainer      user_object;
232*936c8cb4SToby Isaac   PetscLogHandler     h;
233*936c8cb4SToby Isaac   PetscLogHandlerType type;
234*936c8cb4SToby Isaac 
235*936c8cb4SToby Isaac   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
236*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerRegister(PETSC_LOG_HANDLER_EX7, PetscLogHandlerCreate_Ex7));
237*936c8cb4SToby Isaac 
238*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerCreate(PETSC_COMM_WORLD, &h));
239*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerSetType(h, PETSC_LOG_HANDLER_EX7));
240*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerGetType(h, &type));
241*936c8cb4SToby Isaac   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Log handler type is: %s\n", type));
242*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerStart(h));
243*936c8cb4SToby Isaac 
244*936c8cb4SToby Isaac   PetscCall(PetscClassIdRegister("User class", &user_classid));
245*936c8cb4SToby Isaac   PetscCall(PetscLogEventRegister("Event 1", user_classid, &event_1));
246*936c8cb4SToby Isaac   PetscCall(PetscLogEventRegister("Event 2", user_classid, &event_2));
247*936c8cb4SToby Isaac   PetscCall(PetscLogStageRegister("Stage 1", &stage_1));
248*936c8cb4SToby Isaac 
249*936c8cb4SToby Isaac   PetscCall(PetscLogEventBegin(event_1, NULL, NULL, NULL, NULL));
250*936c8cb4SToby Isaac   PetscCall(PetscLogStagePush(stage_1));
251*936c8cb4SToby Isaac   PetscCall(PetscLogEventBegin(event_2, NULL, NULL, NULL, NULL));
252*936c8cb4SToby Isaac   PetscCall(PetscLogEventSync(event_1, PETSC_COMM_WORLD));
253*936c8cb4SToby Isaac   PetscCall(PetscLogEventBegin(event_1, NULL, NULL, NULL, NULL));
254*936c8cb4SToby Isaac   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &user_object));
255*936c8cb4SToby Isaac   PetscCall(PetscContainerDestroy(&user_object));
256*936c8cb4SToby Isaac   PetscCall(PetscLogEventEnd(event_1, NULL, NULL, NULL, NULL));
257*936c8cb4SToby Isaac   PetscCall(PetscLogEventEnd(event_2, NULL, NULL, NULL, NULL));
258*936c8cb4SToby Isaac   PetscCall(PetscLogStagePop());
259*936c8cb4SToby Isaac   PetscCall(PetscLogEventEnd(event_1, NULL, NULL, NULL, NULL));
260*936c8cb4SToby Isaac 
261*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerStop(h));
262*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerView(h, PETSC_VIEWER_STDOUT_WORLD));
263*936c8cb4SToby Isaac   PetscCall(PetscLogHandlerDestroy(&h));
264*936c8cb4SToby Isaac   PetscCall(PetscFinalize());
265*936c8cb4SToby Isaac   return 0;
266*936c8cb4SToby Isaac }
267*936c8cb4SToby Isaac 
268*936c8cb4SToby Isaac /*TEST
269*936c8cb4SToby Isaac 
270*936c8cb4SToby Isaac   test:
271*936c8cb4SToby Isaac     requires: defined(PETSC_USE_LOG)
272*936c8cb4SToby Isaac     suffix: 0
273*936c8cb4SToby Isaac     filter: sed -E "s/:[^:]+:/:time_removed:/g"
274*936c8cb4SToby Isaac 
275*936c8cb4SToby Isaac TEST*/
276