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 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)); \ 58*dff009beSToby Isaac PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d:%-7g:%-33s] " 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 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 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 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)); 192936c8cb4SToby 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)); 193936c8cb4SToby Isaac } 194936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 195936c8cb4SToby Isaac } 196936c8cb4SToby Isaac 197*dff009beSToby Isaac // An example of overloading one of the methods defined using PetscObjectComposeFunction() 198*dff009beSToby Isaac static PetscErrorCode PetscLogHandlerLogObjectState_Ex7(PetscLogHandler h, PetscObject obj, const char format[], va_list argp) 199*dff009beSToby Isaac { 200*dff009beSToby Isaac const char *name; 201*dff009beSToby Isaac 202*dff009beSToby Isaac PetscFunctionBegin; 203*dff009beSToby Isaac PetscCall(PetscObjectGetName(obj, &name)); 204*dff009beSToby Isaac PrintData("Logged state for \"%s\": ", name); 205*dff009beSToby Isaac PetscCall(PetscVFPrintf(PETSC_STDOUT, format, argp)); 206*dff009beSToby Isaac PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 207*dff009beSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 208*dff009beSToby Isaac } 209*dff009beSToby Isaac 210*dff009beSToby Isaac static PetscErrorCode PetscLogHandlerDestroy_Ex7(PetscLogHandler h) 211*dff009beSToby Isaac { 212*dff009beSToby Isaac HandlerCtx ctx; 213*dff009beSToby Isaac 214*dff009beSToby Isaac PetscFunctionBegin; 215*dff009beSToby Isaac ctx = (HandlerCtx)h->data; 216*dff009beSToby Isaac PetscCall(HandlerCtxDestroy(&ctx)); 217*dff009beSToby Isaac PetscCall(PetscObjectComposeFunction((PetscObject)h, "PetscLogHandlerLogObjectState_C", NULL)); 218*dff009beSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 219*dff009beSToby Isaac } 220*dff009beSToby Isaac 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; 237*dff009beSToby Isaac PetscCall(PetscObjectComposeFunction((PetscObject)handler, "PetscLogHandlerLogObjectState_C", PetscLogHandlerLogObjectState_Ex7)); 238936c8cb4SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 239936c8cb4SToby Isaac } 240936c8cb4SToby Isaac 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; 248*dff009beSToby 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)); 270*dff009beSToby Isaac PetscCall(PetscTime(&time)); 271936c8cb4SToby Isaac PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &user_object)); 272*dff009beSToby Isaac PetscCall(PetscObjectSetName((PetscObject)user_object, "User Container")); 273*dff009beSToby 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