xref: /petsc/src/ts/event/tsevent.c (revision d0578d902c0351531261525e6cfec498b8efcc05)
12dc7a7e3SShri Abhyankar 
22dc7a7e3SShri Abhyankar #include <petsc-private/tsimpl.h> /*I  "petscts.h" I*/
32dc7a7e3SShri Abhyankar 
42dc7a7e3SShri Abhyankar #undef __FUNCT__
52dc7a7e3SShri Abhyankar #define __FUNCT__ "TSSetEventMonitor"
62dc7a7e3SShri Abhyankar /*@C
72dc7a7e3SShri Abhyankar    TSSetEventMonitor - Sets a monitoring function used for detecting events
82dc7a7e3SShri Abhyankar 
92dc7a7e3SShri Abhyankar    Logically Collective on TS
102dc7a7e3SShri Abhyankar 
112dc7a7e3SShri Abhyankar    Input Parameters:
122dc7a7e3SShri Abhyankar +  ts - the TS context obtained from TSCreate()
132dc7a7e3SShri Abhyankar .  nevents - number of local events
14d94325d3SShri Abhyankar .  direction - direction of zero crossing to be detected. -1 => Zero crossing in negative direction,
15d94325d3SShri Abhyankar                +1 => Zero crossing in positive direction, 0 => both ways (one for each event)
16d94325d3SShri Abhyankar .  terminate - flag to indicate whether time stepping should be terminated after
17d94325d3SShri Abhyankar                event is detected (one for each event)
182dc7a7e3SShri Abhyankar .  eventmonitor - event monitoring routine
192dc7a7e3SShri Abhyankar .  postevent - [optional] post-event function
202dc7a7e3SShri Abhyankar -  mectx - [optional] user-defined context for private data for the
212dc7a7e3SShri Abhyankar               event monitor and post event routine (use NULL if no
222dc7a7e3SShri Abhyankar               context is desired)
232dc7a7e3SShri Abhyankar 
242dc7a7e3SShri Abhyankar    Calling sequence of eventmonitor:
25d94325d3SShri Abhyankar    PetscErrorCode EventMonitor(TS ts,PetscReal t,Vec U,PetscScalar *fvalue,void* mectx)
262dc7a7e3SShri Abhyankar 
272dc7a7e3SShri Abhyankar    Input Parameters:
282dc7a7e3SShri Abhyankar +  ts  - the TS context
292dc7a7e3SShri Abhyankar .  t   - current time
302dc7a7e3SShri Abhyankar .  U   - current iterate
312dc7a7e3SShri Abhyankar -  ctx - [optional] context passed with eventmonitor
322dc7a7e3SShri Abhyankar 
332dc7a7e3SShri Abhyankar    Output parameters:
34d94325d3SShri Abhyankar .  fvalue    - function value of events at time t
352dc7a7e3SShri Abhyankar 
362dc7a7e3SShri Abhyankar    Calling sequence of postevent:
37031fbad4SShri Abhyankar    PetscErrorCode PostEvent(TS ts,PetscInt nevents_zero, PetscInt events_zero, PetscReal t,Vec U,PetscBool forwardsolve,void* ctx)
382dc7a7e3SShri Abhyankar 
392dc7a7e3SShri Abhyankar    Input Parameters:
402dc7a7e3SShri Abhyankar +  ts - the TS context
412dc7a7e3SShri Abhyankar .  nevents_zero - number of local events whose event function is zero
422dc7a7e3SShri Abhyankar .  events_zero  - indices of local events which have reached zero
432dc7a7e3SShri Abhyankar .  t            - current time
442dc7a7e3SShri Abhyankar .  U            - current solution
45031fbad4SShri Abhyankar .  forwardsolve - Flag to indicate whether TS is doing a forward solve (1) or adjoint solve (0)
462dc7a7e3SShri Abhyankar -  ctx          - the context passed with eventmonitor
472dc7a7e3SShri Abhyankar 
482dc7a7e3SShri Abhyankar    Level: intermediate
492dc7a7e3SShri Abhyankar 
502dc7a7e3SShri Abhyankar .keywords: TS, event, set, monitor
512dc7a7e3SShri Abhyankar 
522dc7a7e3SShri Abhyankar .seealso: TSCreate(), TSSetTimeStep(), TSSetConvergedReason()
532dc7a7e3SShri Abhyankar @*/
54031fbad4SShri Abhyankar PetscErrorCode TSSetEventMonitor(TS ts,PetscInt nevents,PetscInt *direction,PetscBool *terminate,PetscErrorCode (*eventmonitor)(TS,PetscReal,Vec,PetscScalar*,void*),PetscErrorCode (*postevent)(TS,PetscInt,PetscInt[],PetscReal,Vec,PetscBool,void*),void *mectx)
552dc7a7e3SShri Abhyankar {
562dc7a7e3SShri Abhyankar   PetscErrorCode ierr;
572dc7a7e3SShri Abhyankar   PetscReal      t;
582dc7a7e3SShri Abhyankar   Vec            U;
592dc7a7e3SShri Abhyankar   TSEvent        event;
60d94325d3SShri Abhyankar   PetscInt       i;
612dc7a7e3SShri Abhyankar 
622dc7a7e3SShri Abhyankar   PetscFunctionBegin;
6342ea6711SShri   ierr = PetscNew(&event);CHKERRQ(ierr);
64854ce69bSBarry Smith   ierr = PetscMalloc1(nevents,&event->fvalue);CHKERRQ(ierr);
65854ce69bSBarry Smith   ierr = PetscMalloc1(nevents,&event->fvalue_prev);CHKERRQ(ierr);
66854ce69bSBarry Smith   ierr = PetscMalloc1(nevents,&event->direction);CHKERRQ(ierr);
67854ce69bSBarry Smith   ierr = PetscMalloc1(nevents,&event->terminate);CHKERRQ(ierr);
68d94325d3SShri Abhyankar   for (i=0; i < nevents; i++) {
69d94325d3SShri Abhyankar     event->direction[i] = direction[i];
70d94325d3SShri Abhyankar     event->terminate[i] = terminate[i];
71d94325d3SShri Abhyankar   }
72854ce69bSBarry Smith   ierr = PetscMalloc1(nevents,&event->events_zero);CHKERRQ(ierr);
732dc7a7e3SShri Abhyankar   event->monitor = eventmonitor;
742dc7a7e3SShri Abhyankar   event->postevent = postevent;
752dc7a7e3SShri Abhyankar   event->monitorcontext = (void*)mectx;
762dc7a7e3SShri Abhyankar   event->nevents = nevents;
772dc7a7e3SShri Abhyankar 
78f7aea88cSShri Abhyankar   /* Initialize the event recorder */
79f7aea88cSShri Abhyankar   event->recorder.ctr = 0;
80f7aea88cSShri Abhyankar   for(i=0; i < MAXEVENTRECORDERS; i++) {
81f7aea88cSShri Abhyankar     ierr = PetscMalloc1(nevents,&event->recorder.eventidx[i]);CHKERRQ(ierr);
82f7aea88cSShri Abhyankar   }
83f7aea88cSShri Abhyankar 
842dc7a7e3SShri Abhyankar   ierr = TSGetTime(ts,&t);CHKERRQ(ierr);
852dc7a7e3SShri Abhyankar   ierr = TSGetTimeStep(ts,&event->initial_timestep);CHKERRQ(ierr);
862dc7a7e3SShri Abhyankar   ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
872dc7a7e3SShri Abhyankar   event->ptime_prev = t;
88d94325d3SShri Abhyankar   ierr = (*event->monitor)(ts,t,U,event->fvalue_prev,mectx);CHKERRQ(ierr);
892dc7a7e3SShri Abhyankar   ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"TS Event options","");CHKERRQ(ierr);
902dc7a7e3SShri Abhyankar   {
912dc7a7e3SShri Abhyankar     event->tol = 1.0e-6;
922dc7a7e3SShri Abhyankar     ierr = PetscOptionsReal("-ts_event_tol","","",event->tol,&event->tol,NULL);CHKERRQ(ierr);
932dc7a7e3SShri Abhyankar   }
942dc7a7e3SShri Abhyankar   ierr = PetscOptionsEnd();CHKERRQ(ierr);
95d94325d3SShri Abhyankar   ts->event = event;
962dc7a7e3SShri Abhyankar   PetscFunctionReturn(0);
972dc7a7e3SShri Abhyankar }
982dc7a7e3SShri Abhyankar 
992dc7a7e3SShri Abhyankar #undef __FUNCT__
1002dc7a7e3SShri Abhyankar #define __FUNCT__ "TSPostEvent"
101031fbad4SShri Abhyankar /*
102031fbad4SShri Abhyankar    TSPostEvent - Does post event processing by calling the user-defined postevent function
103031fbad4SShri Abhyankar 
104031fbad4SShri Abhyankar    Logically Collective on TS
105031fbad4SShri Abhyankar 
106031fbad4SShri Abhyankar    Input Parameters:
107031fbad4SShri Abhyankar +  ts - the TS context
108031fbad4SShri Abhyankar .  nevents_zero - number of local events whose event function is zero
109031fbad4SShri Abhyankar .  events_zero  - indices of local events which have reached zero
110031fbad4SShri Abhyankar .  t            - current time
111031fbad4SShri Abhyankar .  U            - current solution
112031fbad4SShri Abhyankar .  forwardsolve - Flag to indicate whether TS is doing a forward solve (1) or adjoint solve (0)
113031fbad4SShri Abhyankar -  ctx          - the context passed with eventmonitor
114031fbad4SShri Abhyankar 
115031fbad4SShri Abhyankar    Level: intermediate
116031fbad4SShri Abhyankar 
117031fbad4SShri Abhyankar .keywords: TS, event, set, monitor
118031fbad4SShri Abhyankar 
119031fbad4SShri Abhyankar .seealso: TSSetEventMonitor(),TSEvent
120031fbad4SShri Abhyankar */
121031fbad4SShri Abhyankar #undef __FUNCT__
122031fbad4SShri Abhyankar #define __FUNCT__ "TSPostEvent"
123031fbad4SShri Abhyankar PetscErrorCode TSPostEvent(TS ts,PetscInt nevents_zero,PetscInt events_zero[],PetscReal t,Vec U,PetscBool forwardsolve,void *ctx)
1242dc7a7e3SShri Abhyankar {
1252dc7a7e3SShri Abhyankar   PetscErrorCode ierr;
1262dc7a7e3SShri Abhyankar   TSEvent        event=ts->event;
1272dc7a7e3SShri Abhyankar   PetscBool      terminate=PETSC_FALSE;
128*d0578d90SShri Abhyankar   PetscInt       i,ctr,stepnum;
1292dc7a7e3SShri Abhyankar   PetscBool      ts_terminate;
1302dc7a7e3SShri Abhyankar 
1312dc7a7e3SShri Abhyankar   PetscFunctionBegin;
1322dc7a7e3SShri Abhyankar   if (event->postevent) {
133031fbad4SShri Abhyankar     ierr = (*event->postevent)(ts,nevents_zero,events_zero,t,U,forwardsolve,ctx);CHKERRQ(ierr);
1342dc7a7e3SShri Abhyankar   }
1352dc7a7e3SShri Abhyankar   for(i = 0; i < nevents_zero;i++) {
136e105d053SSatish Balay     terminate = (PetscBool)(terminate || event->terminate[events_zero[i]]);
1372dc7a7e3SShri Abhyankar   }
138b4549700SJed Brown   ierr = MPI_Allreduce(&terminate,&ts_terminate,1,MPIU_BOOL,MPI_LOR,((PetscObject)ts)->comm);CHKERRQ(ierr);
1392dc7a7e3SShri Abhyankar   if (terminate) {
1402dc7a7e3SShri Abhyankar     ierr = TSSetConvergedReason(ts,TS_CONVERGED_EVENT);CHKERRQ(ierr);
1412dc7a7e3SShri Abhyankar     event->status = TSEVENT_NONE;
1422dc7a7e3SShri Abhyankar   } else {
1432dc7a7e3SShri Abhyankar     event->status = TSEVENT_RESET_NEXTSTEP;
1442dc7a7e3SShri Abhyankar   }
145f7aea88cSShri Abhyankar 
146*d0578d90SShri Abhyankar   /* Record the event in the event recorder */
147*d0578d90SShri Abhyankar   ierr = TSGetTimeStepNumber(ts,&stepnum);CHKERRQ(ierr);
148f7aea88cSShri Abhyankar   ctr = event->recorder.ctr;
149f7aea88cSShri Abhyankar   if (ctr == MAXEVENTRECORDERS) {
150f7aea88cSShri Abhyankar     SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Exceeded limit (=%d) for number of events recorded",MAXEVENTRECORDERS);
151f7aea88cSShri Abhyankar   }
152f7aea88cSShri Abhyankar   event->recorder.time[ctr] = t;
153*d0578d90SShri Abhyankar   event->recorder.stepnum[ctr] = stepnum;
154f7aea88cSShri Abhyankar   event->recorder.nevents[ctr] = nevents_zero;
155f7aea88cSShri Abhyankar   for(i=0; i < nevents_zero; i++) event->recorder.eventidx[ctr][i] = events_zero[i];
156f7aea88cSShri Abhyankar   event->recorder.ctr++;
157f7aea88cSShri Abhyankar 
15873967516SShri Abhyankar   /* Reset the event residual functions as states might get changed by the postevent callback */
15973967516SShri Abhyankar   ierr = (*event->monitor)(ts,t,U,event->fvalue_prev,event->monitorcontext);CHKERRQ(ierr);
16073967516SShri Abhyankar   event->ptime_prev  = t;
16173967516SShri Abhyankar 
1622dc7a7e3SShri Abhyankar   PetscFunctionReturn(0);
1632dc7a7e3SShri Abhyankar }
1642dc7a7e3SShri Abhyankar 
1652dc7a7e3SShri Abhyankar #undef __FUNCT__
1662dc7a7e3SShri Abhyankar #define __FUNCT__ "TSEventMonitorDestroy"
1672dc7a7e3SShri Abhyankar PetscErrorCode TSEventMonitorDestroy(TSEvent *event)
1682dc7a7e3SShri Abhyankar {
1692dc7a7e3SShri Abhyankar   PetscErrorCode ierr;
170f7aea88cSShri Abhyankar   PetscInt       i;
1712dc7a7e3SShri Abhyankar 
1722dc7a7e3SShri Abhyankar   PetscFunctionBegin;
1732dc7a7e3SShri Abhyankar   ierr = PetscFree((*event)->fvalue);CHKERRQ(ierr);
1742dc7a7e3SShri Abhyankar   ierr = PetscFree((*event)->fvalue_prev);CHKERRQ(ierr);
1752dc7a7e3SShri Abhyankar   ierr = PetscFree((*event)->direction);CHKERRQ(ierr);
176d94325d3SShri Abhyankar   ierr = PetscFree((*event)->terminate);CHKERRQ(ierr);
1772dc7a7e3SShri Abhyankar   ierr = PetscFree((*event)->events_zero);CHKERRQ(ierr);
178f7aea88cSShri Abhyankar   for(i=0; i < MAXEVENTRECORDERS; i++) {
179f7aea88cSShri Abhyankar     ierr = PetscFree((*event)->recorder.eventidx[i]);
180f7aea88cSShri Abhyankar   }
1812dc7a7e3SShri Abhyankar   ierr = PetscFree(*event);CHKERRQ(ierr);
1822dc7a7e3SShri Abhyankar   *event = NULL;
1832dc7a7e3SShri Abhyankar   PetscFunctionReturn(0);
1842dc7a7e3SShri Abhyankar }
1852dc7a7e3SShri Abhyankar 
1862dc7a7e3SShri Abhyankar #undef __FUNCT__
1872dc7a7e3SShri Abhyankar #define __FUNCT__ "TSEventMonitor"
1882dc7a7e3SShri Abhyankar PetscErrorCode TSEventMonitor(TS ts)
1892dc7a7e3SShri Abhyankar {
1902dc7a7e3SShri Abhyankar   PetscErrorCode ierr;
1912dc7a7e3SShri Abhyankar   TSEvent        event=ts->event;
1922dc7a7e3SShri Abhyankar   PetscReal      t;
1932dc7a7e3SShri Abhyankar   Vec            U;
1942dc7a7e3SShri Abhyankar   PetscInt       i;
1952dc7a7e3SShri Abhyankar   PetscReal      dt;
196b4549700SJed Brown   TSEventStatus  status = event->status;
1972dc7a7e3SShri Abhyankar   PetscInt       rollback=0,in[2],out[2];
198031fbad4SShri Abhyankar   PetscBool      forwardsolve=PETSC_TRUE; /* Flag indicating that TS is doing a forward solve */
1992dc7a7e3SShri Abhyankar 
2002dc7a7e3SShri Abhyankar   PetscFunctionBegin;
2012dc7a7e3SShri Abhyankar 
2022dc7a7e3SShri Abhyankar   ierr = TSGetTime(ts,&t);CHKERRQ(ierr);
2032dc7a7e3SShri Abhyankar   ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
2042dc7a7e3SShri Abhyankar 
2052dc7a7e3SShri Abhyankar   ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr);
2062dc7a7e3SShri Abhyankar   if (event->status == TSEVENT_RESET_NEXTSTEP) {
2072dc7a7e3SShri Abhyankar     /* Take initial time step */
2082dc7a7e3SShri Abhyankar     dt = event->initial_timestep;
2092dc7a7e3SShri Abhyankar     ts->time_step = dt;
2102dc7a7e3SShri Abhyankar     event->status = TSEVENT_NONE;
2112dc7a7e3SShri Abhyankar   }
2122dc7a7e3SShri Abhyankar 
2132dc7a7e3SShri Abhyankar   if (event->status == TSEVENT_NONE) {
2142dc7a7e3SShri Abhyankar     event->tstepend   = t;
2152dc7a7e3SShri Abhyankar   }
2162dc7a7e3SShri Abhyankar 
2172dc7a7e3SShri Abhyankar   event->nevents_zero = 0;
2182dc7a7e3SShri Abhyankar 
219d94325d3SShri Abhyankar   ierr = (*event->monitor)(ts,t,U,event->fvalue,event->monitorcontext);CHKERRQ(ierr);
2202dc7a7e3SShri Abhyankar   if (event->status != TSEVENT_NONE) {
2212dc7a7e3SShri Abhyankar     for (i=0; i < event->nevents; i++) {
222e105d053SSatish Balay       if (PetscAbsScalar(event->fvalue[i]) < event->tol) {
2232dc7a7e3SShri Abhyankar 	event->status = TSEVENT_ZERO;
2242dc7a7e3SShri Abhyankar 	event->events_zero[event->nevents_zero++] = i;
2252dc7a7e3SShri Abhyankar       }
2262dc7a7e3SShri Abhyankar     }
2272dc7a7e3SShri Abhyankar   }
2282dc7a7e3SShri Abhyankar 
2292dc7a7e3SShri Abhyankar   status = event->status;
230b4549700SJed Brown   ierr = MPI_Allreduce((PetscEnum*)&status,(PetscEnum*)&event->status,1,MPIU_ENUM,MPI_MAX,((PetscObject)ts)->comm);CHKERRQ(ierr);
2312dc7a7e3SShri Abhyankar 
2322dc7a7e3SShri Abhyankar   if (event->status == TSEVENT_ZERO) {
233031fbad4SShri Abhyankar     ierr = TSPostEvent(ts,event->nevents_zero,event->events_zero,t,U,forwardsolve,event->monitorcontext);CHKERRQ(ierr);
234c540466cSShri Abhyankar     dt = event->tstepend-t;
235c540466cSShri Abhyankar     if(PetscAbsScalar(dt) < PETSC_SMALL) dt += event->initial_timestep;
236c540466cSShri Abhyankar     ts->time_step = dt;
2372dc7a7e3SShri Abhyankar     PetscFunctionReturn(0);
2382dc7a7e3SShri Abhyankar   }
2392dc7a7e3SShri Abhyankar 
2402dc7a7e3SShri Abhyankar   for (i = 0; i < event->nevents; i++) {
241d94325d3SShri Abhyankar     PetscInt fvalue_sign,fvalueprev_sign;
242d94325d3SShri Abhyankar     fvalue_sign = PetscSign(PetscRealPart(event->fvalue[i]));
243d94325d3SShri Abhyankar     fvalueprev_sign = PetscSign(PetscRealPart(event->fvalue_prev[i]));
2447a728e9fSShri Abhyankar     if (fvalueprev_sign != 0 && (fvalue_sign != fvalueprev_sign)) {
245d94325d3SShri Abhyankar       switch (event->direction[i]) {
246d94325d3SShri Abhyankar       case -1:
247d94325d3SShri Abhyankar 	if (fvalue_sign < 0) {
2482dc7a7e3SShri Abhyankar 	  rollback = 1;
2492dc7a7e3SShri Abhyankar 	  /* Compute linearly interpolated new time step */
250e105d053SSatish Balay 	  dt = PetscMin(dt,PetscRealPart(-event->fvalue_prev[i]*(t - event->ptime_prev)/(event->fvalue[i] - event->fvalue_prev[i])));
2512dc7a7e3SShri Abhyankar 	}
252d94325d3SShri Abhyankar 	break;
253d94325d3SShri Abhyankar       case 1:
254d94325d3SShri Abhyankar 	if (fvalue_sign > 0) {
255d94325d3SShri Abhyankar 	  rollback = 1;
256d94325d3SShri Abhyankar 	  /* Compute linearly interpolated new time step */
257d94325d3SShri Abhyankar 	  dt = PetscMin(dt,PetscRealPart(-event->fvalue_prev[i]*(t - event->ptime_prev)/(event->fvalue[i] - event->fvalue_prev[i])));
2582dc7a7e3SShri Abhyankar 	}
259d94325d3SShri Abhyankar 	break;
260d94325d3SShri Abhyankar       case 0:
261d94325d3SShri Abhyankar 	rollback = 1;
262d94325d3SShri Abhyankar 	/* Compute linearly interpolated new time step */
263d94325d3SShri Abhyankar 	dt = PetscMin(dt,PetscRealPart(-event->fvalue_prev[i]*(t - event->ptime_prev)/(event->fvalue[i] - event->fvalue_prev[i])));
264d94325d3SShri Abhyankar 	break;
265d94325d3SShri Abhyankar       }
266d94325d3SShri Abhyankar     }
267d94325d3SShri Abhyankar   }
268d94325d3SShri Abhyankar   if (rollback) event->status = TSEVENT_LOCATED_INTERVAL;
269d94325d3SShri Abhyankar 
2702dc7a7e3SShri Abhyankar   in[0] = event->status;
2712dc7a7e3SShri Abhyankar   in[1] = rollback;
2722dc7a7e3SShri Abhyankar   ierr = MPI_Allreduce(in,out,2,MPIU_INT,MPI_MAX,((PetscObject)ts)->comm);CHKERRQ(ierr);
2732dc7a7e3SShri Abhyankar 
2742dc7a7e3SShri Abhyankar   rollback = out[1];
2752dc7a7e3SShri Abhyankar   if (rollback) {
2762dc7a7e3SShri Abhyankar     event->status = TSEVENT_LOCATED_INTERVAL;
2772dc7a7e3SShri Abhyankar   }
2782dc7a7e3SShri Abhyankar 
2792dc7a7e3SShri Abhyankar   if (event->status == TSEVENT_LOCATED_INTERVAL) {
2802dc7a7e3SShri Abhyankar     ierr = TSRollBack(ts);CHKERRQ(ierr);
281c540466cSShri Abhyankar     ts->steps--;
282c540466cSShri Abhyankar     ts->total_steps--;
2832dc7a7e3SShri Abhyankar     event->status = TSEVENT_PROCESSING;
2842dc7a7e3SShri Abhyankar   } else {
2852dc7a7e3SShri Abhyankar     for (i = 0; i < event->nevents; i++) {
2862dc7a7e3SShri Abhyankar       event->fvalue_prev[i] = event->fvalue[i];
2872dc7a7e3SShri Abhyankar     }
2882dc7a7e3SShri Abhyankar     event->ptime_prev  = t;
2892dc7a7e3SShri Abhyankar     if (event->status == TSEVENT_PROCESSING) {
2902dc7a7e3SShri Abhyankar       dt = event->tstepend - event->ptime_prev;
2912dc7a7e3SShri Abhyankar     }
2922dc7a7e3SShri Abhyankar   }
293e6b5be14SSatish Balay   ierr = MPI_Allreduce(&dt,&(ts->time_step),1,MPIU_REAL,MPI_MIN,((PetscObject)ts)->comm);CHKERRQ(ierr);
2942dc7a7e3SShri Abhyankar   PetscFunctionReturn(0);
2952dc7a7e3SShri Abhyankar }
2962dc7a7e3SShri Abhyankar 
297*d0578d90SShri Abhyankar #undef __FUNCT__
298*d0578d90SShri Abhyankar #define __FUNCT__ "TSAdjointEventMonitor"
299*d0578d90SShri Abhyankar PetscErrorCode TSAdjointEventMonitor(TS ts)
300*d0578d90SShri Abhyankar {
301*d0578d90SShri Abhyankar   PetscErrorCode ierr;
302*d0578d90SShri Abhyankar   TSEvent        event=ts->event;
303*d0578d90SShri Abhyankar   PetscReal      t;
304*d0578d90SShri Abhyankar   Vec            U;
305*d0578d90SShri Abhyankar   PetscInt       ctr;
306*d0578d90SShri Abhyankar   PetscBool      forwardsolve=PETSC_FALSE; /* Flag indicating that TS is doing an adjoint solve */
307*d0578d90SShri Abhyankar 
308*d0578d90SShri Abhyankar   PetscFunctionBegin;
309*d0578d90SShri Abhyankar 
310*d0578d90SShri Abhyankar   ierr = TSGetTime(ts,&t);CHKERRQ(ierr);
311*d0578d90SShri Abhyankar   ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
312*d0578d90SShri Abhyankar 
313*d0578d90SShri Abhyankar   ctr = event->recorder.ctr-1;
314*d0578d90SShri Abhyankar   if(ctr >= 0 && PetscAbsScalar(t - event->recorder.time[ctr]) < PETSC_SMALL) {
315*d0578d90SShri Abhyankar     /* Call the user postevent function */
316*d0578d90SShri Abhyankar     if(event->postevent) {
317*d0578d90SShri Abhyankar       ierr = (*event->postevent)(ts,event->recorder.nevents[ctr],event->recorder.eventidx[ctr],t,U,forwardsolve,event->monitorcontext);CHKERRQ(ierr);
318*d0578d90SShri Abhyankar       event->recorder.ctr--;
319*d0578d90SShri Abhyankar     }
320*d0578d90SShri Abhyankar   }
321*d0578d90SShri Abhyankar 
322*d0578d90SShri Abhyankar   PetscBarrier((PetscObject)ts);
323*d0578d90SShri Abhyankar   PetscFunctionReturn(0);
324*d0578d90SShri Abhyankar }
325*d0578d90SShri Abhyankar 
326*d0578d90SShri Abhyankar 
327*d0578d90SShri Abhyankar 
328