xref: /petsc/src/ts/event/tsevent.c (revision 031fbad425457fa56461e7568655f046a0cf1d1f)
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:
37*031fbad4SShri 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
45*031fbad4SShri 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 @*/
54*031fbad4SShri 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 
782dc7a7e3SShri Abhyankar   ierr = TSGetTime(ts,&t);CHKERRQ(ierr);
792dc7a7e3SShri Abhyankar   ierr = TSGetTimeStep(ts,&event->initial_timestep);CHKERRQ(ierr);
802dc7a7e3SShri Abhyankar   ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
812dc7a7e3SShri Abhyankar   event->ptime_prev = t;
82d94325d3SShri Abhyankar   ierr = (*event->monitor)(ts,t,U,event->fvalue_prev,mectx);CHKERRQ(ierr);
832dc7a7e3SShri Abhyankar   ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"TS Event options","");CHKERRQ(ierr);
842dc7a7e3SShri Abhyankar   {
852dc7a7e3SShri Abhyankar     event->tol = 1.0e-6;
862dc7a7e3SShri Abhyankar     ierr = PetscOptionsReal("-ts_event_tol","","",event->tol,&event->tol,NULL);CHKERRQ(ierr);
872dc7a7e3SShri Abhyankar   }
882dc7a7e3SShri Abhyankar   ierr = PetscOptionsEnd();CHKERRQ(ierr);
89d94325d3SShri Abhyankar   ts->event = event;
902dc7a7e3SShri Abhyankar   PetscFunctionReturn(0);
912dc7a7e3SShri Abhyankar }
922dc7a7e3SShri Abhyankar 
932dc7a7e3SShri Abhyankar #undef __FUNCT__
942dc7a7e3SShri Abhyankar #define __FUNCT__ "TSPostEvent"
95*031fbad4SShri Abhyankar /*
96*031fbad4SShri Abhyankar    TSPostEvent - Does post event processing by calling the user-defined postevent function
97*031fbad4SShri Abhyankar 
98*031fbad4SShri Abhyankar    Logically Collective on TS
99*031fbad4SShri Abhyankar 
100*031fbad4SShri Abhyankar    Input Parameters:
101*031fbad4SShri Abhyankar +  ts - the TS context
102*031fbad4SShri Abhyankar .  nevents_zero - number of local events whose event function is zero
103*031fbad4SShri Abhyankar .  events_zero  - indices of local events which have reached zero
104*031fbad4SShri Abhyankar .  t            - current time
105*031fbad4SShri Abhyankar .  U            - current solution
106*031fbad4SShri Abhyankar .  forwardsolve - Flag to indicate whether TS is doing a forward solve (1) or adjoint solve (0)
107*031fbad4SShri Abhyankar -  ctx          - the context passed with eventmonitor
108*031fbad4SShri Abhyankar 
109*031fbad4SShri Abhyankar    Level: intermediate
110*031fbad4SShri Abhyankar 
111*031fbad4SShri Abhyankar .keywords: TS, event, set, monitor
112*031fbad4SShri Abhyankar 
113*031fbad4SShri Abhyankar .seealso: TSSetEventMonitor(),TSEvent
114*031fbad4SShri Abhyankar */
115*031fbad4SShri Abhyankar #undef __FUNCT__
116*031fbad4SShri Abhyankar #define __FUNCT__ "TSPostEvent"
117*031fbad4SShri Abhyankar PetscErrorCode TSPostEvent(TS ts,PetscInt nevents_zero,PetscInt events_zero[],PetscReal t,Vec U,PetscBool forwardsolve,void *ctx)
1182dc7a7e3SShri Abhyankar {
1192dc7a7e3SShri Abhyankar   PetscErrorCode ierr;
1202dc7a7e3SShri Abhyankar   TSEvent        event=ts->event;
1212dc7a7e3SShri Abhyankar   PetscBool      terminate=PETSC_FALSE;
1222dc7a7e3SShri Abhyankar   PetscInt       i;
1232dc7a7e3SShri Abhyankar   PetscBool      ts_terminate;
1242dc7a7e3SShri Abhyankar 
1252dc7a7e3SShri Abhyankar   PetscFunctionBegin;
1262dc7a7e3SShri Abhyankar   if (event->postevent) {
127*031fbad4SShri Abhyankar     ierr = (*event->postevent)(ts,nevents_zero,events_zero,t,U,forwardsolve,ctx);CHKERRQ(ierr);
1282dc7a7e3SShri Abhyankar   }
1292dc7a7e3SShri Abhyankar   for(i = 0; i < nevents_zero;i++) {
130e105d053SSatish Balay     terminate = (PetscBool)(terminate || event->terminate[events_zero[i]]);
1312dc7a7e3SShri Abhyankar   }
132b4549700SJed Brown   ierr = MPI_Allreduce(&terminate,&ts_terminate,1,MPIU_BOOL,MPI_LOR,((PetscObject)ts)->comm);CHKERRQ(ierr);
1332dc7a7e3SShri Abhyankar   if (terminate) {
1342dc7a7e3SShri Abhyankar     ierr = TSSetConvergedReason(ts,TS_CONVERGED_EVENT);CHKERRQ(ierr);
1352dc7a7e3SShri Abhyankar     event->status = TSEVENT_NONE;
1362dc7a7e3SShri Abhyankar   } else {
1372dc7a7e3SShri Abhyankar     event->status = TSEVENT_RESET_NEXTSTEP;
1382dc7a7e3SShri Abhyankar   }
1392dc7a7e3SShri Abhyankar   PetscFunctionReturn(0);
1402dc7a7e3SShri Abhyankar }
1412dc7a7e3SShri Abhyankar 
1422dc7a7e3SShri Abhyankar #undef __FUNCT__
1432dc7a7e3SShri Abhyankar #define __FUNCT__ "TSEventMonitorDestroy"
1442dc7a7e3SShri Abhyankar PetscErrorCode TSEventMonitorDestroy(TSEvent *event)
1452dc7a7e3SShri Abhyankar {
1462dc7a7e3SShri Abhyankar   PetscErrorCode ierr;
1472dc7a7e3SShri Abhyankar 
1482dc7a7e3SShri Abhyankar   PetscFunctionBegin;
1492dc7a7e3SShri Abhyankar   ierr = PetscFree((*event)->fvalue);CHKERRQ(ierr);
1502dc7a7e3SShri Abhyankar   ierr = PetscFree((*event)->fvalue_prev);CHKERRQ(ierr);
1512dc7a7e3SShri Abhyankar   ierr = PetscFree((*event)->direction);CHKERRQ(ierr);
152d94325d3SShri Abhyankar   ierr = PetscFree((*event)->terminate);CHKERRQ(ierr);
1532dc7a7e3SShri Abhyankar   ierr = PetscFree((*event)->events_zero);CHKERRQ(ierr);
1542dc7a7e3SShri Abhyankar   ierr = PetscFree(*event);CHKERRQ(ierr);
1552dc7a7e3SShri Abhyankar   *event = NULL;
1562dc7a7e3SShri Abhyankar   PetscFunctionReturn(0);
1572dc7a7e3SShri Abhyankar }
1582dc7a7e3SShri Abhyankar 
1592dc7a7e3SShri Abhyankar #undef __FUNCT__
1602dc7a7e3SShri Abhyankar #define __FUNCT__ "TSEventMonitor"
1612dc7a7e3SShri Abhyankar PetscErrorCode TSEventMonitor(TS ts)
1622dc7a7e3SShri Abhyankar {
1632dc7a7e3SShri Abhyankar   PetscErrorCode ierr;
1642dc7a7e3SShri Abhyankar   TSEvent        event=ts->event;
1652dc7a7e3SShri Abhyankar   PetscReal      t;
1662dc7a7e3SShri Abhyankar   Vec            U;
1672dc7a7e3SShri Abhyankar   PetscInt       i;
1682dc7a7e3SShri Abhyankar   PetscReal      dt;
169b4549700SJed Brown   TSEventStatus  status = event->status;
1702dc7a7e3SShri Abhyankar   PetscInt       rollback=0,in[2],out[2];
171*031fbad4SShri Abhyankar   PetscBool      forwardsolve=PETSC_TRUE; /* Flag indicating that TS is doing a forward solve */
1722dc7a7e3SShri Abhyankar 
1732dc7a7e3SShri Abhyankar   PetscFunctionBegin;
1742dc7a7e3SShri Abhyankar 
1752dc7a7e3SShri Abhyankar   ierr = TSGetTime(ts,&t);CHKERRQ(ierr);
1762dc7a7e3SShri Abhyankar   ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
1772dc7a7e3SShri Abhyankar 
1782dc7a7e3SShri Abhyankar   ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr);
1792dc7a7e3SShri Abhyankar   if (event->status == TSEVENT_RESET_NEXTSTEP) {
1802dc7a7e3SShri Abhyankar     /* Take initial time step */
1812dc7a7e3SShri Abhyankar     dt = event->initial_timestep;
1822dc7a7e3SShri Abhyankar     ts->time_step = dt;
1832dc7a7e3SShri Abhyankar     event->status = TSEVENT_NONE;
1842dc7a7e3SShri Abhyankar   }
1852dc7a7e3SShri Abhyankar 
1862dc7a7e3SShri Abhyankar   if (event->status == TSEVENT_NONE) {
1872dc7a7e3SShri Abhyankar     event->tstepend   = t;
1882dc7a7e3SShri Abhyankar   }
1892dc7a7e3SShri Abhyankar 
1902dc7a7e3SShri Abhyankar   event->nevents_zero = 0;
1912dc7a7e3SShri Abhyankar 
192d94325d3SShri Abhyankar   ierr = (*event->monitor)(ts,t,U,event->fvalue,event->monitorcontext);CHKERRQ(ierr);
1932dc7a7e3SShri Abhyankar   if (event->status != TSEVENT_NONE) {
1942dc7a7e3SShri Abhyankar     for (i=0; i < event->nevents; i++) {
195e105d053SSatish Balay       if (PetscAbsScalar(event->fvalue[i]) < event->tol) {
1962dc7a7e3SShri Abhyankar 	event->status = TSEVENT_ZERO;
1972dc7a7e3SShri Abhyankar 	event->events_zero[event->nevents_zero++] = i;
1982dc7a7e3SShri Abhyankar       }
1992dc7a7e3SShri Abhyankar     }
2002dc7a7e3SShri Abhyankar   }
2012dc7a7e3SShri Abhyankar 
2022dc7a7e3SShri Abhyankar   status = event->status;
203b4549700SJed Brown   ierr = MPI_Allreduce((PetscEnum*)&status,(PetscEnum*)&event->status,1,MPIU_ENUM,MPI_MAX,((PetscObject)ts)->comm);CHKERRQ(ierr);
2042dc7a7e3SShri Abhyankar 
2052dc7a7e3SShri Abhyankar   if (event->status == TSEVENT_ZERO) {
2062dc7a7e3SShri Abhyankar     dt = event->tstepend-t;
2072dc7a7e3SShri Abhyankar     ts->time_step = dt;
208*031fbad4SShri Abhyankar     ierr = TSPostEvent(ts,event->nevents_zero,event->events_zero,t,U,forwardsolve,event->monitorcontext);CHKERRQ(ierr);
2092dc7a7e3SShri Abhyankar     for (i = 0; i < event->nevents; i++) {
2102dc7a7e3SShri Abhyankar       event->fvalue_prev[i] = event->fvalue[i];
2112dc7a7e3SShri Abhyankar     }
2122dc7a7e3SShri Abhyankar     event->ptime_prev  = t;
2132dc7a7e3SShri Abhyankar     PetscFunctionReturn(0);
2142dc7a7e3SShri Abhyankar   }
2152dc7a7e3SShri Abhyankar 
2162dc7a7e3SShri Abhyankar   for (i = 0; i < event->nevents; i++) {
217d94325d3SShri Abhyankar     PetscInt fvalue_sign,fvalueprev_sign;
218d94325d3SShri Abhyankar     fvalue_sign = PetscSign(PetscRealPart(event->fvalue[i]));
219d94325d3SShri Abhyankar     fvalueprev_sign = PetscSign(PetscRealPart(event->fvalue_prev[i]));
2207a728e9fSShri Abhyankar     if (fvalueprev_sign != 0 && (fvalue_sign != fvalueprev_sign)) {
221d94325d3SShri Abhyankar       switch (event->direction[i]) {
222d94325d3SShri Abhyankar       case -1:
223d94325d3SShri Abhyankar 	if (fvalue_sign < 0) {
2242dc7a7e3SShri Abhyankar 	  rollback = 1;
2252dc7a7e3SShri Abhyankar 	  /* Compute linearly interpolated new time step */
226e105d053SSatish Balay 	  dt = PetscMin(dt,PetscRealPart(-event->fvalue_prev[i]*(t - event->ptime_prev)/(event->fvalue[i] - event->fvalue_prev[i])));
2272dc7a7e3SShri Abhyankar 	}
228d94325d3SShri Abhyankar 	break;
229d94325d3SShri Abhyankar       case 1:
230d94325d3SShri Abhyankar 	if (fvalue_sign > 0) {
231d94325d3SShri Abhyankar 	  rollback = 1;
232d94325d3SShri Abhyankar 	  /* Compute linearly interpolated new time step */
233d94325d3SShri Abhyankar 	  dt = PetscMin(dt,PetscRealPart(-event->fvalue_prev[i]*(t - event->ptime_prev)/(event->fvalue[i] - event->fvalue_prev[i])));
2342dc7a7e3SShri Abhyankar 	}
235d94325d3SShri Abhyankar 	break;
236d94325d3SShri Abhyankar       case 0:
237d94325d3SShri Abhyankar 	rollback = 1;
238d94325d3SShri Abhyankar 	/* Compute linearly interpolated new time step */
239d94325d3SShri Abhyankar 	dt = PetscMin(dt,PetscRealPart(-event->fvalue_prev[i]*(t - event->ptime_prev)/(event->fvalue[i] - event->fvalue_prev[i])));
240d94325d3SShri Abhyankar 	break;
241d94325d3SShri Abhyankar       }
242d94325d3SShri Abhyankar     }
243d94325d3SShri Abhyankar   }
244d94325d3SShri Abhyankar   if (rollback) event->status = TSEVENT_LOCATED_INTERVAL;
245d94325d3SShri Abhyankar 
2462dc7a7e3SShri Abhyankar   in[0] = event->status;
2472dc7a7e3SShri Abhyankar   in[1] = rollback;
2482dc7a7e3SShri Abhyankar   ierr = MPI_Allreduce(in,out,2,MPIU_INT,MPI_MAX,((PetscObject)ts)->comm);CHKERRQ(ierr);
2492dc7a7e3SShri Abhyankar 
2502dc7a7e3SShri Abhyankar   rollback = out[1];
2512dc7a7e3SShri Abhyankar   if (rollback) {
2522dc7a7e3SShri Abhyankar     event->status = TSEVENT_LOCATED_INTERVAL;
2532dc7a7e3SShri Abhyankar   }
2542dc7a7e3SShri Abhyankar 
2552dc7a7e3SShri Abhyankar   if (event->status == TSEVENT_LOCATED_INTERVAL) {
2562dc7a7e3SShri Abhyankar     ierr = TSRollBack(ts);CHKERRQ(ierr);
2572dc7a7e3SShri Abhyankar     event->status = TSEVENT_PROCESSING;
2582dc7a7e3SShri Abhyankar   } else {
2592dc7a7e3SShri Abhyankar     for (i = 0; i < event->nevents; i++) {
2602dc7a7e3SShri Abhyankar       event->fvalue_prev[i] = event->fvalue[i];
2612dc7a7e3SShri Abhyankar     }
2622dc7a7e3SShri Abhyankar     event->ptime_prev  = t;
2632dc7a7e3SShri Abhyankar     if (event->status == TSEVENT_PROCESSING) {
2642dc7a7e3SShri Abhyankar       dt = event->tstepend - event->ptime_prev;
2652dc7a7e3SShri Abhyankar     }
2662dc7a7e3SShri Abhyankar   }
267e6b5be14SSatish Balay   ierr = MPI_Allreduce(&dt,&(ts->time_step),1,MPIU_REAL,MPI_MIN,((PetscObject)ts)->comm);CHKERRQ(ierr);
2682dc7a7e3SShri Abhyankar   PetscFunctionReturn(0);
2692dc7a7e3SShri Abhyankar }
2702dc7a7e3SShri Abhyankar 
271