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 19*294de794SToby 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 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 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)); \ 58936c8cb4SToby Isaac PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d:%-7g:%-29s] " format_string, _rank, _time, PETSC_FUNCTION_NAME, __VA_ARGS__)); \ 59936c8cb4SToby Isaac } while (0) 60936c8cb4SToby Isaac 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; 76936c8cb4SToby Isaac PetscCall(PetscHMapIGetWithDefault(ctx->running, (PetscInt)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); 80936c8cb4SToby Isaac PetscCall(PetscHMapISet(ctx->running, (PetscInt)e, count)); 81936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 82936c8cb4SToby Isaac } 83936c8cb4SToby Isaac 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)); 94936c8cb4SToby Isaac PetscCall(PetscHMapIGetWithDefault(ctx->running, (PetscInt)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); 98936c8cb4SToby Isaac PetscCall(PetscHMapISet(ctx->running, (PetscInt)e, count)); 99936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 100936c8cb4SToby Isaac } 101936c8cb4SToby Isaac 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)); 114936c8cb4SToby Isaac PrintData("Event \"%s\" synced: took %g seconds\n", event_info.name, (double)time); 115936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 116936c8cb4SToby Isaac } 117936c8cb4SToby Isaac 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 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 138936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerDestroy_Ex7(PetscLogHandler h) 139936c8cb4SToby Isaac { 140936c8cb4SToby Isaac HandlerCtx ctx; 141936c8cb4SToby Isaac 142936c8cb4SToby Isaac PetscFunctionBegin; 143936c8cb4SToby Isaac ctx = (HandlerCtx)h->data; 144936c8cb4SToby Isaac PetscCall(HandlerCtxDestroy(&ctx)); 145936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 146936c8cb4SToby Isaac } 147936c8cb4SToby Isaac 148936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerStagePush_Ex7(PetscLogHandler h, PetscLogStage new_stage) 149936c8cb4SToby Isaac { 150936c8cb4SToby Isaac PetscLogStage old_stage; 151936c8cb4SToby Isaac PetscLogStageInfo new_info; 152936c8cb4SToby Isaac PetscLogState state; 153936c8cb4SToby Isaac 154936c8cb4SToby Isaac PetscFunctionBegin; 155936c8cb4SToby Isaac PetscCall(PetscLogHandlerGetState(h, &state)); 156936c8cb4SToby Isaac PetscCall(PetscLogStateStageGetInfo(state, new_stage, &new_info)); 157936c8cb4SToby Isaac PetscCall(PetscLogStateGetCurrentStage(state, &old_stage)); 158936c8cb4SToby Isaac if (old_stage >= 0) { 159936c8cb4SToby Isaac PetscLogStageInfo old_info; 160936c8cb4SToby Isaac PetscCall(PetscLogStateStageGetInfo(state, old_stage, &old_info)); 161936c8cb4SToby Isaac PrintData("Pushing stage stage \"%s\" (replacing \"%s\")\n", new_info.name, old_info.name); 162936c8cb4SToby Isaac } else { 163936c8cb4SToby Isaac PrintData("Pushing initial stage \"%s\"\n", new_info.name); 164936c8cb4SToby Isaac } 165936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 166936c8cb4SToby Isaac } 167936c8cb4SToby Isaac 168936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerStagePop_Ex7(PetscLogHandler h, PetscLogStage old_stage) 169936c8cb4SToby Isaac { 170936c8cb4SToby Isaac PetscLogStage new_stage; 171936c8cb4SToby Isaac PetscLogStageInfo old_info; 172936c8cb4SToby Isaac PetscLogState state; 173936c8cb4SToby Isaac 174936c8cb4SToby Isaac PetscFunctionBegin; 175936c8cb4SToby Isaac PetscCall(PetscLogHandlerGetState(h, &state)); 176936c8cb4SToby Isaac PetscCall(PetscLogStateStageGetInfo(state, old_stage, &old_info)); 177936c8cb4SToby Isaac PetscCall(PetscLogStateGetCurrentStage(state, &new_stage)); 178936c8cb4SToby Isaac if (new_stage >= 0) { 179936c8cb4SToby Isaac PetscLogStageInfo new_info; 180936c8cb4SToby Isaac 181936c8cb4SToby Isaac PetscCall(PetscLogStateStageGetInfo(state, new_stage, &new_info)); 182936c8cb4SToby Isaac PrintData("Popping stage \"%s\" (back to \"%s\")\n", old_info.name, new_info.name); 183936c8cb4SToby Isaac } else { 184936c8cb4SToby Isaac PrintData("Popping initial stage \"%s\"\n", old_info.name); 185936c8cb4SToby Isaac } 186936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 187936c8cb4SToby Isaac } 188936c8cb4SToby Isaac 189936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerView_Ex7(PetscLogHandler h, PetscViewer viewer) 190936c8cb4SToby Isaac { 191936c8cb4SToby Isaac PetscBool is_ascii; 192936c8cb4SToby Isaac 193936c8cb4SToby Isaac PetscFunctionBegin; 194936c8cb4SToby Isaac PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &is_ascii)); 195936c8cb4SToby Isaac if (is_ascii) { 196936c8cb4SToby Isaac HandlerCtx ctx; 197936c8cb4SToby Isaac PetscInt num_entries; 198936c8cb4SToby Isaac 199936c8cb4SToby Isaac ctx = (HandlerCtx)h->data; 200936c8cb4SToby Isaac PetscCall(PetscHMapIGetSize(ctx->running, &num_entries)); 201936c8cb4SToby Isaac PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " events were seen by the handler\n", num_entries)); 202936c8cb4SToby 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)); 203936c8cb4SToby Isaac } 204936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 205936c8cb4SToby Isaac } 206936c8cb4SToby Isaac 207936c8cb4SToby Isaac static PetscErrorCode PetscLogHandlerCreate_Ex7(PetscLogHandler handler) 208936c8cb4SToby Isaac { 209936c8cb4SToby Isaac HandlerCtx ctx; 210936c8cb4SToby Isaac 211936c8cb4SToby Isaac PetscFunctionBegin; 212936c8cb4SToby Isaac PetscCall(HandlerCtxCreate(&ctx)); 213936c8cb4SToby Isaac handler->data = (void *)ctx; 214936c8cb4SToby Isaac handler->ops->destroy = PetscLogHandlerDestroy_Ex7; 215936c8cb4SToby Isaac handler->ops->view = PetscLogHandlerView_Ex7; 216936c8cb4SToby Isaac handler->ops->eventbegin = PetscLogHandlerEventBegin_Ex7; 217936c8cb4SToby Isaac handler->ops->eventend = PetscLogHandlerEventEnd_Ex7; 218936c8cb4SToby Isaac handler->ops->eventsync = PetscLogHandlerEventSync_Ex7; 219936c8cb4SToby Isaac handler->ops->objectcreate = PetscLogHandlerObjectCreate_Ex7; 220936c8cb4SToby Isaac handler->ops->objectdestroy = PetscLogHandlerObjectDestroy_Ex7; 221936c8cb4SToby Isaac handler->ops->stagepush = PetscLogHandlerStagePush_Ex7; 222936c8cb4SToby Isaac handler->ops->stagepop = PetscLogHandlerStagePop_Ex7; 223936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 224936c8cb4SToby Isaac } 225936c8cb4SToby Isaac 226936c8cb4SToby Isaac int main(int argc, char **argv) 227936c8cb4SToby Isaac { 228936c8cb4SToby Isaac PetscClassId user_classid; 229936c8cb4SToby Isaac PetscLogEvent event_1, event_2; 230936c8cb4SToby Isaac PetscLogStage stage_1; 231936c8cb4SToby Isaac PetscContainer user_object; 232936c8cb4SToby Isaac PetscLogHandler h; 233936c8cb4SToby Isaac PetscLogHandlerType type; 234936c8cb4SToby Isaac 235936c8cb4SToby Isaac PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 236*294de794SToby Isaac PetscCall(PetscLogHandlerRegister(PETSCLOGHANDLEREX7, PetscLogHandlerCreate_Ex7)); 237936c8cb4SToby Isaac 238936c8cb4SToby Isaac PetscCall(PetscLogHandlerCreate(PETSC_COMM_WORLD, &h)); 239*294de794SToby Isaac PetscCall(PetscLogHandlerSetType(h, PETSCLOGHANDLEREX7)); 240936c8cb4SToby Isaac PetscCall(PetscLogHandlerGetType(h, &type)); 241936c8cb4SToby Isaac PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Log handler type is: %s\n", type)); 242936c8cb4SToby Isaac PetscCall(PetscLogHandlerStart(h)); 243936c8cb4SToby Isaac 244936c8cb4SToby Isaac PetscCall(PetscClassIdRegister("User class", &user_classid)); 245936c8cb4SToby Isaac PetscCall(PetscLogEventRegister("Event 1", user_classid, &event_1)); 246936c8cb4SToby Isaac PetscCall(PetscLogEventRegister("Event 2", user_classid, &event_2)); 247936c8cb4SToby Isaac PetscCall(PetscLogStageRegister("Stage 1", &stage_1)); 248936c8cb4SToby Isaac 249936c8cb4SToby Isaac PetscCall(PetscLogEventBegin(event_1, NULL, NULL, NULL, NULL)); 250936c8cb4SToby Isaac PetscCall(PetscLogStagePush(stage_1)); 251936c8cb4SToby Isaac PetscCall(PetscLogEventBegin(event_2, NULL, NULL, NULL, NULL)); 252936c8cb4SToby Isaac PetscCall(PetscLogEventSync(event_1, PETSC_COMM_WORLD)); 253936c8cb4SToby Isaac PetscCall(PetscLogEventBegin(event_1, NULL, NULL, NULL, NULL)); 254936c8cb4SToby Isaac PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &user_object)); 255936c8cb4SToby Isaac PetscCall(PetscContainerDestroy(&user_object)); 256936c8cb4SToby Isaac PetscCall(PetscLogEventEnd(event_1, NULL, NULL, NULL, NULL)); 257936c8cb4SToby Isaac PetscCall(PetscLogEventEnd(event_2, NULL, NULL, NULL, NULL)); 258936c8cb4SToby Isaac PetscCall(PetscLogStagePop()); 259936c8cb4SToby Isaac PetscCall(PetscLogEventEnd(event_1, NULL, NULL, NULL, NULL)); 260936c8cb4SToby Isaac 261936c8cb4SToby Isaac PetscCall(PetscLogHandlerStop(h)); 262936c8cb4SToby Isaac PetscCall(PetscLogHandlerView(h, PETSC_VIEWER_STDOUT_WORLD)); 263936c8cb4SToby Isaac PetscCall(PetscLogHandlerDestroy(&h)); 264936c8cb4SToby Isaac PetscCall(PetscFinalize()); 265936c8cb4SToby Isaac return 0; 266936c8cb4SToby Isaac } 267936c8cb4SToby Isaac 268936c8cb4SToby Isaac /*TEST 269936c8cb4SToby Isaac 270936c8cb4SToby Isaac test: 271936c8cb4SToby Isaac requires: defined(PETSC_USE_LOG) 272936c8cb4SToby Isaac suffix: 0 273936c8cb4SToby Isaac filter: sed -E "s/:[^:]+:/:time_removed:/g" 274936c8cb4SToby Isaac 275936c8cb4SToby Isaac TEST*/ 276