xref: /petsc/src/sys/tutorials/ex7.c (revision be37439ebbbdb2f81c3420c175a94aa72e59929c)
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