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