xref: /petsc/src/ts/event/tsevent.c (revision e30051953a40c1c935962522139e028164bf04d4)
12dc7a7e3SShri Abhyankar 
2af0996ceSBarry Smith #include <petsc/private/tsimpl.h> /*I  "petscts.h" I*/
32dc7a7e3SShri Abhyankar 
42dc7a7e3SShri Abhyankar #undef __FUNCT__
56fea3669SShri Abhyankar #define __FUNCT__ "TSEventMonitorInitialize"
66fea3669SShri Abhyankar /*
76fea3669SShri Abhyankar   TSEventMonitorInitialize - Initializes TSEvent for TSSolve
86fea3669SShri Abhyankar */
96fea3669SShri Abhyankar PetscErrorCode TSEventMonitorInitialize(TS ts)
106fea3669SShri Abhyankar {
116fea3669SShri Abhyankar   PetscErrorCode ierr;
126fea3669SShri Abhyankar   PetscReal      t;
136fea3669SShri Abhyankar   Vec            U;
146fea3669SShri Abhyankar   TSEvent        event=ts->event;
156fea3669SShri Abhyankar 
166fea3669SShri Abhyankar   PetscFunctionBegin;
176fea3669SShri Abhyankar 
186fea3669SShri Abhyankar   ierr = TSGetTime(ts,&t);CHKERRQ(ierr);
196fea3669SShri Abhyankar   ierr = TSGetTimeStep(ts,&event->initial_timestep);CHKERRQ(ierr);
206fea3669SShri Abhyankar   ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
216fea3669SShri Abhyankar   event->ptime_prev = t;
226fea3669SShri Abhyankar   ierr = (*event->monitor)(ts,t,U,event->fvalue_prev,event->monitorcontext);CHKERRQ(ierr);
236fea3669SShri Abhyankar 
246fea3669SShri Abhyankar   /* Initialize the event recorder */
256fea3669SShri Abhyankar   event->recorder.ctr = 0;
266fea3669SShri Abhyankar 
276fea3669SShri Abhyankar   PetscFunctionReturn(0);
286fea3669SShri Abhyankar }
296fea3669SShri Abhyankar 
306fea3669SShri Abhyankar #undef __FUNCT__
31*e3005195SShri Abhyankar #define __FUNCT__ "TSSetEventTolerances"
32*e3005195SShri Abhyankar /*@
33*e3005195SShri Abhyankar    TSSetEventTolerances - Set tolerances for event zero crossings when using event handler
34*e3005195SShri Abhyankar 
35*e3005195SShri Abhyankar    Logically Collective
36*e3005195SShri Abhyankar 
37*e3005195SShri Abhyankar    Input Arguments:
38*e3005195SShri Abhyankar +  ts - time integration context
39*e3005195SShri Abhyankar .  tol - scalar tolerance, PETSC_DECIDE to leave current value
40*e3005195SShri Abhyankar -  vtol - array of tolerances or NULL, used in preference to tol if present
41*e3005195SShri Abhyankar 
42*e3005195SShri Abhyankar -  -ts_event_tol <tol> tolerance for event zero crossing
43*e3005195SShri Abhyankar 
44*e3005195SShri Abhyankar    Notes:
45*e3005195SShri Abhyankar    Must call TSSetEventMonitor() before setting the tolerances.
46*e3005195SShri Abhyankar 
47*e3005195SShri Abhyankar    The size of vtol is equal to the number of events.
48*e3005195SShri Abhyankar 
49*e3005195SShri Abhyankar    Level: beginner
50*e3005195SShri Abhyankar 
51*e3005195SShri Abhyankar .seealso: TS, TSEvent, TSSetEventMonitor()
52*e3005195SShri Abhyankar @*/
53*e3005195SShri Abhyankar PetscErrorCode TSSetEventTolerances(TS ts,PetscReal tol,PetscReal *vtol)
54*e3005195SShri Abhyankar {
55*e3005195SShri Abhyankar   TSEvent        event=ts->event;
56*e3005195SShri Abhyankar   PetscInt       i;
57*e3005195SShri Abhyankar 
58*e3005195SShri Abhyankar   PetscFunctionBegin;
59*e3005195SShri Abhyankar   if(!ts->event) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must set the events first by calling TSSetEventMonitor()");
60*e3005195SShri Abhyankar   if(vtol) {
61*e3005195SShri Abhyankar     for(i=0; i < event->nevents; i++) event->vtol[i] = vtol[i];
62*e3005195SShri Abhyankar   } else {
63*e3005195SShri Abhyankar     if(tol != PETSC_DECIDE || tol != PETSC_DEFAULT) {
64*e3005195SShri Abhyankar       for(i=0; i < event->nevents; i++) event->vtol[i] = tol;
65*e3005195SShri Abhyankar     }
66*e3005195SShri Abhyankar   }
67*e3005195SShri Abhyankar   PetscFunctionReturn(0);
68*e3005195SShri Abhyankar }
69*e3005195SShri Abhyankar 
70*e3005195SShri Abhyankar #undef __FUNCT__
712dc7a7e3SShri Abhyankar #define __FUNCT__ "TSSetEventMonitor"
722dc7a7e3SShri Abhyankar /*@C
732dc7a7e3SShri Abhyankar    TSSetEventMonitor - Sets a monitoring function used for detecting events
742dc7a7e3SShri Abhyankar 
752dc7a7e3SShri Abhyankar    Logically Collective on TS
762dc7a7e3SShri Abhyankar 
772dc7a7e3SShri Abhyankar    Input Parameters:
782dc7a7e3SShri Abhyankar +  ts - the TS context obtained from TSCreate()
792dc7a7e3SShri Abhyankar .  nevents - number of local events
80d94325d3SShri Abhyankar .  direction - direction of zero crossing to be detected. -1 => Zero crossing in negative direction,
81d94325d3SShri Abhyankar                +1 => Zero crossing in positive direction, 0 => both ways (one for each event)
82d94325d3SShri Abhyankar .  terminate - flag to indicate whether time stepping should be terminated after
83d94325d3SShri Abhyankar                event is detected (one for each event)
842dc7a7e3SShri Abhyankar .  eventmonitor - event monitoring routine
852dc7a7e3SShri Abhyankar .  postevent - [optional] post-event function
862dc7a7e3SShri Abhyankar -  mectx - [optional] user-defined context for private data for the
872dc7a7e3SShri Abhyankar               event monitor and post event routine (use NULL if no
882dc7a7e3SShri Abhyankar               context is desired)
892dc7a7e3SShri Abhyankar 
902dc7a7e3SShri Abhyankar    Calling sequence of eventmonitor:
91d94325d3SShri Abhyankar    PetscErrorCode EventMonitor(TS ts,PetscReal t,Vec U,PetscScalar *fvalue,void* mectx)
922dc7a7e3SShri Abhyankar 
932dc7a7e3SShri Abhyankar    Input Parameters:
942dc7a7e3SShri Abhyankar +  ts  - the TS context
952dc7a7e3SShri Abhyankar .  t   - current time
962dc7a7e3SShri Abhyankar .  U   - current iterate
972dc7a7e3SShri Abhyankar -  ctx - [optional] context passed with eventmonitor
982dc7a7e3SShri Abhyankar 
992dc7a7e3SShri Abhyankar    Output parameters:
100d94325d3SShri Abhyankar .  fvalue    - function value of events at time t
1012dc7a7e3SShri Abhyankar 
1022dc7a7e3SShri Abhyankar    Calling sequence of postevent:
103031fbad4SShri Abhyankar    PetscErrorCode PostEvent(TS ts,PetscInt nevents_zero, PetscInt events_zero, PetscReal t,Vec U,PetscBool forwardsolve,void* ctx)
1042dc7a7e3SShri Abhyankar 
1052dc7a7e3SShri Abhyankar    Input Parameters:
1062dc7a7e3SShri Abhyankar +  ts - the TS context
1072dc7a7e3SShri Abhyankar .  nevents_zero - number of local events whose event function is zero
1082dc7a7e3SShri Abhyankar .  events_zero  - indices of local events which have reached zero
1092dc7a7e3SShri Abhyankar .  t            - current time
1102dc7a7e3SShri Abhyankar .  U            - current solution
111031fbad4SShri Abhyankar .  forwardsolve - Flag to indicate whether TS is doing a forward solve (1) or adjoint solve (0)
1122dc7a7e3SShri Abhyankar -  ctx          - the context passed with eventmonitor
1132dc7a7e3SShri Abhyankar 
1142dc7a7e3SShri Abhyankar    Level: intermediate
1152dc7a7e3SShri Abhyankar 
1162dc7a7e3SShri Abhyankar .keywords: TS, event, set, monitor
1172dc7a7e3SShri Abhyankar 
1182dc7a7e3SShri Abhyankar .seealso: TSCreate(), TSSetTimeStep(), TSSetConvergedReason()
1192dc7a7e3SShri Abhyankar @*/
120031fbad4SShri 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)
1212dc7a7e3SShri Abhyankar {
1222dc7a7e3SShri Abhyankar   PetscErrorCode ierr;
1232dc7a7e3SShri Abhyankar   TSEvent        event;
124d94325d3SShri Abhyankar   PetscInt       i;
125006e6a18SShri Abhyankar   PetscBool      flg;
126*e3005195SShri Abhyankar   PetscReal      tol=1e-6;
1272dc7a7e3SShri Abhyankar 
1282dc7a7e3SShri Abhyankar   PetscFunctionBegin;
12942ea6711SShri   ierr = PetscNew(&event);CHKERRQ(ierr);
130854ce69bSBarry Smith   ierr = PetscMalloc1(nevents,&event->fvalue);CHKERRQ(ierr);
131854ce69bSBarry Smith   ierr = PetscMalloc1(nevents,&event->fvalue_prev);CHKERRQ(ierr);
132854ce69bSBarry Smith   ierr = PetscMalloc1(nevents,&event->direction);CHKERRQ(ierr);
133854ce69bSBarry Smith   ierr = PetscMalloc1(nevents,&event->terminate);CHKERRQ(ierr);
134*e3005195SShri Abhyankar   ierr = PetscMalloc1(nevents,&event->vtol);CHKERRQ(ierr);
135d94325d3SShri Abhyankar   for (i=0; i < nevents; i++) {
136d94325d3SShri Abhyankar     event->direction[i] = direction[i];
137d94325d3SShri Abhyankar     event->terminate[i] = terminate[i];
138d94325d3SShri Abhyankar   }
139854ce69bSBarry Smith   ierr = PetscMalloc1(nevents,&event->events_zero);CHKERRQ(ierr);
1402dc7a7e3SShri Abhyankar   event->monitor = eventmonitor;
1412dc7a7e3SShri Abhyankar   event->postevent = postevent;
1422dc7a7e3SShri Abhyankar   event->monitorcontext = (void*)mectx;
1432dc7a7e3SShri Abhyankar   event->nevents = nevents;
1442dc7a7e3SShri Abhyankar 
145f7aea88cSShri Abhyankar   for(i=0; i < MAXEVENTRECORDERS; i++) {
146f7aea88cSShri Abhyankar     ierr = PetscMalloc1(nevents,&event->recorder.eventidx[i]);CHKERRQ(ierr);
147f7aea88cSShri Abhyankar   }
148f7aea88cSShri Abhyankar 
1492dc7a7e3SShri Abhyankar   ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"TS Event options","");CHKERRQ(ierr);
1502dc7a7e3SShri Abhyankar   {
151*e3005195SShri Abhyankar     ierr = PetscOptionsReal("-ts_event_tol","Scalar event tolerance for zero crossing check","",tol,&tol,NULL);CHKERRQ(ierr);
152006e6a18SShri Abhyankar     ierr = PetscOptionsName("-ts_event_monitor","Print choices made by event handler","",&flg);CHKERRQ(ierr);
1532dc7a7e3SShri Abhyankar   }
154*e3005195SShri Abhyankar 
155*e3005195SShri Abhyankar   for(i=0; i < event->nevents; i++) event->vtol[i] = tol;
1562dc7a7e3SShri Abhyankar   ierr = PetscOptionsEnd();CHKERRQ(ierr);
157006e6a18SShri Abhyankar 
158006e6a18SShri Abhyankar   if(flg) {
159006e6a18SShri Abhyankar     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ts),"stdout",&event->mon);CHKERRQ(ierr);
160006e6a18SShri Abhyankar   }
161d94325d3SShri Abhyankar   ts->event = event;
1622dc7a7e3SShri Abhyankar   PetscFunctionReturn(0);
1632dc7a7e3SShri Abhyankar }
1642dc7a7e3SShri Abhyankar 
1652dc7a7e3SShri Abhyankar #undef __FUNCT__
1662dc7a7e3SShri Abhyankar #define __FUNCT__ "TSPostEvent"
167031fbad4SShri Abhyankar /*
168031fbad4SShri Abhyankar    TSPostEvent - Does post event processing by calling the user-defined postevent function
169031fbad4SShri Abhyankar 
170031fbad4SShri Abhyankar    Logically Collective on TS
171031fbad4SShri Abhyankar 
172031fbad4SShri Abhyankar    Input Parameters:
173031fbad4SShri Abhyankar +  ts - the TS context
174031fbad4SShri Abhyankar .  nevents_zero - number of local events whose event function is zero
175031fbad4SShri Abhyankar .  events_zero  - indices of local events which have reached zero
176031fbad4SShri Abhyankar .  t            - current time
177031fbad4SShri Abhyankar .  U            - current solution
178031fbad4SShri Abhyankar .  forwardsolve - Flag to indicate whether TS is doing a forward solve (1) or adjoint solve (0)
179031fbad4SShri Abhyankar -  ctx          - the context passed with eventmonitor
180031fbad4SShri Abhyankar 
181031fbad4SShri Abhyankar    Level: intermediate
182031fbad4SShri Abhyankar 
183031fbad4SShri Abhyankar .keywords: TS, event, set, monitor
184031fbad4SShri Abhyankar 
185031fbad4SShri Abhyankar .seealso: TSSetEventMonitor(),TSEvent
186031fbad4SShri Abhyankar */
187031fbad4SShri Abhyankar #undef __FUNCT__
188031fbad4SShri Abhyankar #define __FUNCT__ "TSPostEvent"
189031fbad4SShri Abhyankar PetscErrorCode TSPostEvent(TS ts,PetscInt nevents_zero,PetscInt events_zero[],PetscReal t,Vec U,PetscBool forwardsolve,void *ctx)
1902dc7a7e3SShri Abhyankar {
1912dc7a7e3SShri Abhyankar   PetscErrorCode ierr;
1922dc7a7e3SShri Abhyankar   TSEvent        event=ts->event;
1932dc7a7e3SShri Abhyankar   PetscBool      terminate=PETSC_FALSE;
194d0578d90SShri Abhyankar   PetscInt       i,ctr,stepnum;
1952dc7a7e3SShri Abhyankar   PetscBool      ts_terminate;
1962dc7a7e3SShri Abhyankar 
1972dc7a7e3SShri Abhyankar   PetscFunctionBegin;
1982dc7a7e3SShri Abhyankar   if (event->postevent) {
199031fbad4SShri Abhyankar     ierr = (*event->postevent)(ts,nevents_zero,events_zero,t,U,forwardsolve,ctx);CHKERRQ(ierr);
2002dc7a7e3SShri Abhyankar   }
2012dc7a7e3SShri Abhyankar   for(i = 0; i < nevents_zero;i++) {
202e105d053SSatish Balay     terminate = (PetscBool)(terminate || event->terminate[events_zero[i]]);
2032dc7a7e3SShri Abhyankar   }
204b4549700SJed Brown   ierr = MPI_Allreduce(&terminate,&ts_terminate,1,MPIU_BOOL,MPI_LOR,((PetscObject)ts)->comm);CHKERRQ(ierr);
2052dc7a7e3SShri Abhyankar   if (terminate) {
2062dc7a7e3SShri Abhyankar     ierr = TSSetConvergedReason(ts,TS_CONVERGED_EVENT);CHKERRQ(ierr);
2072dc7a7e3SShri Abhyankar     event->status = TSEVENT_NONE;
2082dc7a7e3SShri Abhyankar   } else {
2092dc7a7e3SShri Abhyankar     event->status = TSEVENT_RESET_NEXTSTEP;
2102dc7a7e3SShri Abhyankar   }
211f7aea88cSShri Abhyankar 
212d0578d90SShri Abhyankar   /* Record the event in the event recorder */
213d0578d90SShri Abhyankar   ierr = TSGetTimeStepNumber(ts,&stepnum);CHKERRQ(ierr);
214f7aea88cSShri Abhyankar   ctr = event->recorder.ctr;
215f7aea88cSShri Abhyankar   if (ctr == MAXEVENTRECORDERS) {
216f7aea88cSShri Abhyankar     SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Exceeded limit (=%d) for number of events recorded",MAXEVENTRECORDERS);
217f7aea88cSShri Abhyankar   }
218f7aea88cSShri Abhyankar   event->recorder.time[ctr] = t;
219d0578d90SShri Abhyankar   event->recorder.stepnum[ctr] = stepnum;
220f7aea88cSShri Abhyankar   event->recorder.nevents[ctr] = nevents_zero;
221f7aea88cSShri Abhyankar   for(i=0; i < nevents_zero; i++) event->recorder.eventidx[ctr][i] = events_zero[i];
222f7aea88cSShri Abhyankar   event->recorder.ctr++;
223f7aea88cSShri Abhyankar 
22473967516SShri Abhyankar   /* Reset the event residual functions as states might get changed by the postevent callback */
22573967516SShri Abhyankar   ierr = (*event->monitor)(ts,t,U,event->fvalue_prev,event->monitorcontext);CHKERRQ(ierr);
22673967516SShri Abhyankar   event->ptime_prev  = t;
22773967516SShri Abhyankar 
2282dc7a7e3SShri Abhyankar   PetscFunctionReturn(0);
2292dc7a7e3SShri Abhyankar }
2302dc7a7e3SShri Abhyankar 
2312dc7a7e3SShri Abhyankar #undef __FUNCT__
2322dc7a7e3SShri Abhyankar #define __FUNCT__ "TSEventMonitorDestroy"
2332dc7a7e3SShri Abhyankar PetscErrorCode TSEventMonitorDestroy(TSEvent *event)
2342dc7a7e3SShri Abhyankar {
2352dc7a7e3SShri Abhyankar   PetscErrorCode ierr;
236f7aea88cSShri Abhyankar   PetscInt       i;
2372dc7a7e3SShri Abhyankar 
2382dc7a7e3SShri Abhyankar   PetscFunctionBegin;
2392dc7a7e3SShri Abhyankar   ierr = PetscFree((*event)->fvalue);CHKERRQ(ierr);
2402dc7a7e3SShri Abhyankar   ierr = PetscFree((*event)->fvalue_prev);CHKERRQ(ierr);
2412dc7a7e3SShri Abhyankar   ierr = PetscFree((*event)->direction);CHKERRQ(ierr);
242d94325d3SShri Abhyankar   ierr = PetscFree((*event)->terminate);CHKERRQ(ierr);
2432dc7a7e3SShri Abhyankar   ierr = PetscFree((*event)->events_zero);CHKERRQ(ierr);
244*e3005195SShri Abhyankar   ierr = PetscFree((*event)->vtol);CHKERRQ(ierr);
245f7aea88cSShri Abhyankar   for(i=0; i < MAXEVENTRECORDERS; i++) {
246302440fdSBarry Smith     ierr = PetscFree((*event)->recorder.eventidx[i]);CHKERRQ(ierr);
247f7aea88cSShri Abhyankar   }
248006e6a18SShri Abhyankar   ierr = PetscViewerDestroy(&(*event)->mon);CHKERRQ(ierr);
2492dc7a7e3SShri Abhyankar   ierr = PetscFree(*event);CHKERRQ(ierr);
2502dc7a7e3SShri Abhyankar   *event = NULL;
2512dc7a7e3SShri Abhyankar   PetscFunctionReturn(0);
2522dc7a7e3SShri Abhyankar }
2532dc7a7e3SShri Abhyankar 
2542dc7a7e3SShri Abhyankar #undef __FUNCT__
2552dc7a7e3SShri Abhyankar #define __FUNCT__ "TSEventMonitor"
2562dc7a7e3SShri Abhyankar PetscErrorCode TSEventMonitor(TS ts)
2572dc7a7e3SShri Abhyankar {
2582dc7a7e3SShri Abhyankar   PetscErrorCode ierr;
2592dc7a7e3SShri Abhyankar   TSEvent        event=ts->event;
2602dc7a7e3SShri Abhyankar   PetscReal      t;
2612dc7a7e3SShri Abhyankar   Vec            U;
2622dc7a7e3SShri Abhyankar   PetscInt       i;
2632dc7a7e3SShri Abhyankar   PetscReal      dt;
264b4549700SJed Brown   TSEventStatus  status = event->status;
2652dc7a7e3SShri Abhyankar   PetscInt       rollback=0,in[2],out[2];
266031fbad4SShri Abhyankar   PetscBool      forwardsolve=PETSC_TRUE; /* Flag indicating that TS is doing a forward solve */
2672dc7a7e3SShri Abhyankar 
2682dc7a7e3SShri Abhyankar   PetscFunctionBegin;
2692dc7a7e3SShri Abhyankar 
2702dc7a7e3SShri Abhyankar   ierr = TSGetTime(ts,&t);CHKERRQ(ierr);
2712dc7a7e3SShri Abhyankar   ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
2722dc7a7e3SShri Abhyankar 
2732dc7a7e3SShri Abhyankar   ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr);
2742dc7a7e3SShri Abhyankar   if (event->status == TSEVENT_RESET_NEXTSTEP) {
2752dc7a7e3SShri Abhyankar     /* Take initial time step */
2762dc7a7e3SShri Abhyankar     dt = event->initial_timestep;
2772dc7a7e3SShri Abhyankar     ts->time_step = dt;
2782dc7a7e3SShri Abhyankar     event->status = TSEVENT_NONE;
2792dc7a7e3SShri Abhyankar   }
2802dc7a7e3SShri Abhyankar 
2812dc7a7e3SShri Abhyankar   if (event->status == TSEVENT_NONE) {
2822dc7a7e3SShri Abhyankar     event->tstepend   = t;
2832dc7a7e3SShri Abhyankar   }
2842dc7a7e3SShri Abhyankar 
2852dc7a7e3SShri Abhyankar   event->nevents_zero = 0;
2862dc7a7e3SShri Abhyankar 
287d94325d3SShri Abhyankar   ierr = (*event->monitor)(ts,t,U,event->fvalue,event->monitorcontext);CHKERRQ(ierr);
2882dc7a7e3SShri Abhyankar   for (i=0; i < event->nevents; i++) {
289*e3005195SShri Abhyankar     if (PetscAbsScalar(event->fvalue[i]) < event->vtol[i]) {
2902dc7a7e3SShri Abhyankar       event->status = TSEVENT_ZERO;
2912dc7a7e3SShri Abhyankar       event->events_zero[event->nevents_zero++] = i;
292006e6a18SShri Abhyankar       if(event->mon) {
293006e6a18SShri Abhyankar 	ierr = PetscViewerASCIIPrintf(event->mon,"TSEvent : Event %D zero crossing at time %g\n",i,(double)t);CHKERRQ(ierr);
294006e6a18SShri Abhyankar       }
2952dc7a7e3SShri Abhyankar     }
2962dc7a7e3SShri Abhyankar   }
2972dc7a7e3SShri Abhyankar 
2982dc7a7e3SShri Abhyankar   status = event->status;
299b4549700SJed Brown   ierr = MPI_Allreduce((PetscEnum*)&status,(PetscEnum*)&event->status,1,MPIU_ENUM,MPI_MAX,((PetscObject)ts)->comm);CHKERRQ(ierr);
3002dc7a7e3SShri Abhyankar 
3012dc7a7e3SShri Abhyankar   if (event->status == TSEVENT_ZERO) {
302031fbad4SShri Abhyankar     ierr = TSPostEvent(ts,event->nevents_zero,event->events_zero,t,U,forwardsolve,event->monitorcontext);CHKERRQ(ierr);
303c540466cSShri Abhyankar     dt = event->tstepend-t;
304bcbf8bb3SShri Abhyankar     if(PetscAbsReal(dt) < PETSC_SMALL) dt += event->initial_timestep;
30593fbeba1SShri Abhyankar     ierr = TSSetTimeStep(ts,dt);CHKERRQ(ierr);
3062dc7a7e3SShri Abhyankar     PetscFunctionReturn(0);
3072dc7a7e3SShri Abhyankar   }
3082dc7a7e3SShri Abhyankar 
3092dc7a7e3SShri Abhyankar   for (i = 0; i < event->nevents; i++) {
310d94325d3SShri Abhyankar     PetscInt fvalue_sign,fvalueprev_sign;
311d94325d3SShri Abhyankar     fvalue_sign = PetscSign(PetscRealPart(event->fvalue[i]));
312d94325d3SShri Abhyankar     fvalueprev_sign = PetscSign(PetscRealPart(event->fvalue_prev[i]));
313*e3005195SShri Abhyankar     if (fvalueprev_sign != 0 && (fvalue_sign != fvalueprev_sign) && (PetscAbsScalar(event->fvalue_prev[i]) > event->vtol[i])) {
314d94325d3SShri Abhyankar       switch (event->direction[i]) {
315d94325d3SShri Abhyankar       case -1:
316d94325d3SShri Abhyankar 	if (fvalue_sign < 0) {
3172dc7a7e3SShri Abhyankar 	  rollback = 1;
3182dc7a7e3SShri Abhyankar 	  /* Compute linearly interpolated new time step */
319e105d053SSatish Balay 	  dt = PetscMin(dt,PetscRealPart(-event->fvalue_prev[i]*(t - event->ptime_prev)/(event->fvalue[i] - event->fvalue_prev[i])));
320006e6a18SShri Abhyankar 	  if(event->mon) {
321006e6a18SShri Abhyankar 	    ierr = PetscViewerASCIIPrintf(event->mon,"TSEvent : Event %D interval located [%g - %g]\n",i,(double)event->ptime_prev,(double)t);CHKERRQ(ierr);
322006e6a18SShri Abhyankar 	  }
3232dc7a7e3SShri Abhyankar 	}
324d94325d3SShri Abhyankar 	break;
325d94325d3SShri Abhyankar       case 1:
326d94325d3SShri Abhyankar 	if (fvalue_sign > 0) {
327d94325d3SShri Abhyankar 	  rollback = 1;
328d94325d3SShri Abhyankar 	  /* Compute linearly interpolated new time step */
329d94325d3SShri Abhyankar 	  dt = PetscMin(dt,PetscRealPart(-event->fvalue_prev[i]*(t - event->ptime_prev)/(event->fvalue[i] - event->fvalue_prev[i])));
330006e6a18SShri Abhyankar 	  if(event->mon) {
331006e6a18SShri Abhyankar 	    ierr = PetscViewerASCIIPrintf(event->mon,"TSEvent : Event %D interval located [%g - %g]\n",i,(double)event->ptime_prev,(double)t);CHKERRQ(ierr);
332006e6a18SShri Abhyankar 	  }
3332dc7a7e3SShri Abhyankar 	}
334d94325d3SShri Abhyankar 	break;
335d94325d3SShri Abhyankar       case 0:
336d94325d3SShri Abhyankar 	rollback = 1;
337d94325d3SShri Abhyankar 	/* Compute linearly interpolated new time step */
338d94325d3SShri Abhyankar 	dt = PetscMin(dt,PetscRealPart(-event->fvalue_prev[i]*(t - event->ptime_prev)/(event->fvalue[i] - event->fvalue_prev[i])));
339006e6a18SShri Abhyankar 	if(event->mon) {
340006e6a18SShri Abhyankar 	  ierr = PetscViewerASCIIPrintf(event->mon,"TSEvent : Event %D interval located [%g - %g]\n",i,(double)event->ptime_prev,(double)t);CHKERRQ(ierr);
341006e6a18SShri Abhyankar 	}
342d94325d3SShri Abhyankar 	break;
343d94325d3SShri Abhyankar       }
344d94325d3SShri Abhyankar     }
345d94325d3SShri Abhyankar   }
346d94325d3SShri Abhyankar   if (rollback) event->status = TSEVENT_LOCATED_INTERVAL;
347d94325d3SShri Abhyankar 
3482dc7a7e3SShri Abhyankar   in[0] = event->status;
3492dc7a7e3SShri Abhyankar   in[1] = rollback;
3502dc7a7e3SShri Abhyankar   ierr = MPI_Allreduce(in,out,2,MPIU_INT,MPI_MAX,((PetscObject)ts)->comm);CHKERRQ(ierr);
3512dc7a7e3SShri Abhyankar 
3522dc7a7e3SShri Abhyankar   rollback = out[1];
3532dc7a7e3SShri Abhyankar   if (rollback) {
3542dc7a7e3SShri Abhyankar     event->status = TSEVENT_LOCATED_INTERVAL;
3552dc7a7e3SShri Abhyankar   }
3562dc7a7e3SShri Abhyankar 
3572dc7a7e3SShri Abhyankar   if (event->status == TSEVENT_LOCATED_INTERVAL) {
3582dc7a7e3SShri Abhyankar     ierr = TSRollBack(ts);CHKERRQ(ierr);
359c540466cSShri Abhyankar     ts->steps--;
360c540466cSShri Abhyankar     ts->total_steps--;
361db84a1feSShri Abhyankar     ts->reason = TS_CONVERGED_ITERATING;
3622dc7a7e3SShri Abhyankar     event->status = TSEVENT_PROCESSING;
3632dc7a7e3SShri Abhyankar   } else {
3642dc7a7e3SShri Abhyankar     for (i = 0; i < event->nevents; i++) {
3652dc7a7e3SShri Abhyankar       event->fvalue_prev[i] = event->fvalue[i];
3662dc7a7e3SShri Abhyankar     }
3672dc7a7e3SShri Abhyankar     event->ptime_prev  = t;
3682dc7a7e3SShri Abhyankar     if (event->status == TSEVENT_PROCESSING) {
3692dc7a7e3SShri Abhyankar       dt = event->tstepend - event->ptime_prev;
3702dc7a7e3SShri Abhyankar     }
3712dc7a7e3SShri Abhyankar   }
372a9b180a6SBarry Smith   ierr = MPI_Allreduce(&dt,&(ts->time_step),1,MPIU_REAL,MPIU_MIN,((PetscObject)ts)->comm);CHKERRQ(ierr);
3732dc7a7e3SShri Abhyankar   PetscFunctionReturn(0);
3742dc7a7e3SShri Abhyankar }
3752dc7a7e3SShri Abhyankar 
376d0578d90SShri Abhyankar #undef __FUNCT__
377d0578d90SShri Abhyankar #define __FUNCT__ "TSAdjointEventMonitor"
378d0578d90SShri Abhyankar PetscErrorCode TSAdjointEventMonitor(TS ts)
379d0578d90SShri Abhyankar {
380d0578d90SShri Abhyankar   PetscErrorCode ierr;
381d0578d90SShri Abhyankar   TSEvent        event=ts->event;
382d0578d90SShri Abhyankar   PetscReal      t;
383d0578d90SShri Abhyankar   Vec            U;
384d0578d90SShri Abhyankar   PetscInt       ctr;
385d0578d90SShri Abhyankar   PetscBool      forwardsolve=PETSC_FALSE; /* Flag indicating that TS is doing an adjoint solve */
386d0578d90SShri Abhyankar 
387d0578d90SShri Abhyankar   PetscFunctionBegin;
388d0578d90SShri Abhyankar 
389d0578d90SShri Abhyankar   ierr = TSGetTime(ts,&t);CHKERRQ(ierr);
390d0578d90SShri Abhyankar   ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
391d0578d90SShri Abhyankar 
392d0578d90SShri Abhyankar   ctr = event->recorder.ctr-1;
393bcbf8bb3SShri Abhyankar   if(ctr >= 0 && PetscAbsReal(t - event->recorder.time[ctr]) < PETSC_SMALL) {
394d0578d90SShri Abhyankar     /* Call the user postevent function */
395d0578d90SShri Abhyankar     if(event->postevent) {
396d0578d90SShri Abhyankar       ierr = (*event->postevent)(ts,event->recorder.nevents[ctr],event->recorder.eventidx[ctr],t,U,forwardsolve,event->monitorcontext);CHKERRQ(ierr);
397d0578d90SShri Abhyankar       event->recorder.ctr--;
398d0578d90SShri Abhyankar     }
399d0578d90SShri Abhyankar   }
400d0578d90SShri Abhyankar 
401d0578d90SShri Abhyankar   PetscBarrier((PetscObject)ts);
402d0578d90SShri Abhyankar   PetscFunctionReturn(0);
403d0578d90SShri Abhyankar }
404d0578d90SShri Abhyankar 
405d0578d90SShri Abhyankar 
406d0578d90SShri Abhyankar 
407