1af0996ceSBarry Smith #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 22dc7a7e3SShri Abhyankar 36fea3669SShri Abhyankar /* 46427ac75SLisandro Dalcin TSEventInitialize - Initializes TSEvent for TSSolve 56fea3669SShri Abhyankar */ 66427ac75SLisandro Dalcin PetscErrorCode TSEventInitialize(TSEvent event,TS ts,PetscReal t,Vec U) 76fea3669SShri Abhyankar { 86fea3669SShri Abhyankar PetscErrorCode ierr; 96fea3669SShri Abhyankar 106fea3669SShri Abhyankar PetscFunctionBegin; 116427ac75SLisandro Dalcin if (!event) PetscFunctionReturn(0); 126427ac75SLisandro Dalcin PetscValidPointer(event,1); 136427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,2); 146427ac75SLisandro Dalcin PetscValidHeaderSpecific(U,VEC_CLASSID,4); 156fea3669SShri Abhyankar event->ptime_prev = t; 1638bf2713SShri Abhyankar event->iterctr = 0; 176427ac75SLisandro Dalcin ierr = (*event->eventhandler)(ts,t,U,event->fvalue_prev,event->ctx);CHKERRQ(ierr); 186fea3669SShri Abhyankar PetscFunctionReturn(0); 196fea3669SShri Abhyankar } 206fea3669SShri Abhyankar 217dbe0728SLisandro Dalcin PetscErrorCode TSEventDestroy(TSEvent *event) 227dbe0728SLisandro Dalcin { 237dbe0728SLisandro Dalcin PetscErrorCode ierr; 247dbe0728SLisandro Dalcin PetscInt i; 257dbe0728SLisandro Dalcin 267dbe0728SLisandro Dalcin PetscFunctionBegin; 277dbe0728SLisandro Dalcin PetscValidPointer(event,1); 287dbe0728SLisandro Dalcin if (!*event) PetscFunctionReturn(0); 29c793f718SLisandro Dalcin if (--(*event)->refct > 0) {*event = NULL; PetscFunctionReturn(0);} 30e7069c78SShri 317dbe0728SLisandro Dalcin ierr = PetscFree((*event)->fvalue);CHKERRQ(ierr); 327dbe0728SLisandro Dalcin ierr = PetscFree((*event)->fvalue_prev);CHKERRQ(ierr); 33e2cdd850SShri Abhyankar ierr = PetscFree((*event)->fvalue_right);CHKERRQ(ierr); 34e2cdd850SShri Abhyankar ierr = PetscFree((*event)->zerocrossing);CHKERRQ(ierr); 35e2cdd850SShri Abhyankar ierr = PetscFree((*event)->side);CHKERRQ(ierr); 367dbe0728SLisandro Dalcin ierr = PetscFree((*event)->direction);CHKERRQ(ierr); 377dbe0728SLisandro Dalcin ierr = PetscFree((*event)->terminate);CHKERRQ(ierr); 387dbe0728SLisandro Dalcin ierr = PetscFree((*event)->events_zero);CHKERRQ(ierr); 397dbe0728SLisandro Dalcin ierr = PetscFree((*event)->vtol);CHKERRQ(ierr); 40a4ffd976SShri Abhyankar 41a4ffd976SShri Abhyankar for (i=0; i < (*event)->recsize; i++) { 427dbe0728SLisandro Dalcin ierr = PetscFree((*event)->recorder.eventidx[i]);CHKERRQ(ierr); 437dbe0728SLisandro Dalcin } 44a4ffd976SShri Abhyankar ierr = PetscFree((*event)->recorder.eventidx);CHKERRQ(ierr); 45a4ffd976SShri Abhyankar ierr = PetscFree((*event)->recorder.nevents);CHKERRQ(ierr); 46a4ffd976SShri Abhyankar ierr = PetscFree((*event)->recorder.stepnum);CHKERRQ(ierr); 47a4ffd976SShri Abhyankar ierr = PetscFree((*event)->recorder.time);CHKERRQ(ierr); 48a4ffd976SShri Abhyankar 497dbe0728SLisandro Dalcin ierr = PetscViewerDestroy(&(*event)->monitor);CHKERRQ(ierr); 507dbe0728SLisandro Dalcin ierr = PetscFree(*event);CHKERRQ(ierr); 517dbe0728SLisandro Dalcin PetscFunctionReturn(0); 527dbe0728SLisandro Dalcin } 537dbe0728SLisandro Dalcin 54e3005195SShri Abhyankar /*@ 55ac6a796dSBarry Smith TSSetPostEventIntervalStep - Set the time-step used immediately following the event interval 56458122a4SShri Abhyankar 57458122a4SShri Abhyankar Logically Collective 58458122a4SShri Abhyankar 59458122a4SShri Abhyankar Input Arguments: 60458122a4SShri Abhyankar + ts - time integration context 61458122a4SShri Abhyankar - dt - post event interval step 62458122a4SShri Abhyankar 63458122a4SShri Abhyankar Options Database Keys: 64458122a4SShri Abhyankar . -ts_event_post_eventinterval_step <dt> time-step after event interval 65458122a4SShri Abhyankar 66458122a4SShri Abhyankar Notes: 67ac6a796dSBarry Smith TSSetPostEventIntervalStep allows one to set a time-step that is used immediately following an event interval. 68458122a4SShri Abhyankar 69458122a4SShri Abhyankar This function should be called from the postevent function set with TSSetEventHandler(). 70458122a4SShri Abhyankar 71458122a4SShri Abhyankar The post event interval time-step should be selected based on the dynamics following the event. 72458122a4SShri Abhyankar If the dynamics are stiff, a conservative (small) step should be used. 73458122a4SShri Abhyankar If not, then a larger time-step can be used. 74458122a4SShri Abhyankar 75458122a4SShri Abhyankar Level: Advanced 76458122a4SShri Abhyankar .seealso: TS, TSEvent, TSSetEventHandler() 77458122a4SShri Abhyankar @*/ 78458122a4SShri Abhyankar PetscErrorCode TSSetPostEventIntervalStep(TS ts,PetscReal dt) 79458122a4SShri Abhyankar { 80458122a4SShri Abhyankar PetscFunctionBegin; 81458122a4SShri Abhyankar ts->event->timestep_posteventinterval = dt; 82458122a4SShri Abhyankar PetscFunctionReturn(0); 83458122a4SShri Abhyankar } 84458122a4SShri Abhyankar 85458122a4SShri Abhyankar /*@ 86e3005195SShri Abhyankar TSSetEventTolerances - Set tolerances for event zero crossings when using event handler 87e3005195SShri Abhyankar 88e3005195SShri Abhyankar Logically Collective 89e3005195SShri Abhyankar 90e3005195SShri Abhyankar Input Arguments: 91e3005195SShri Abhyankar + ts - time integration context 92e3005195SShri Abhyankar . tol - scalar tolerance, PETSC_DECIDE to leave current value 93e3005195SShri Abhyankar - vtol - array of tolerances or NULL, used in preference to tol if present 94e3005195SShri Abhyankar 952589fa24SLisandro Dalcin Options Database Keys: 962589fa24SLisandro Dalcin . -ts_event_tol <tol> tolerance for event zero crossing 97e3005195SShri Abhyankar 98e3005195SShri Abhyankar Notes: 99f25fe674SLisandro Dalcin Must call TSSetEventHandler() before setting the tolerances. 100e3005195SShri Abhyankar 101e3005195SShri Abhyankar The size of vtol is equal to the number of events. 102e3005195SShri Abhyankar 103e3005195SShri Abhyankar Level: beginner 104e3005195SShri Abhyankar 105f25fe674SLisandro Dalcin .seealso: TS, TSEvent, TSSetEventHandler() 106e3005195SShri Abhyankar @*/ 1076427ac75SLisandro Dalcin PetscErrorCode TSSetEventTolerances(TS ts,PetscReal tol,PetscReal vtol[]) 108e3005195SShri Abhyankar { 1096427ac75SLisandro Dalcin TSEvent event; 110e3005195SShri Abhyankar PetscInt i; 111e3005195SShri Abhyankar 112e3005195SShri Abhyankar PetscFunctionBegin; 1136427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1146427ac75SLisandro Dalcin if (vtol) PetscValidRealPointer(vtol,3); 115f25fe674SLisandro Dalcin if (!ts->event) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must set the events first by calling TSSetEventHandler()"); 1166427ac75SLisandro Dalcin 1176427ac75SLisandro Dalcin event = ts->event; 118e3005195SShri Abhyankar if (vtol) { 119e3005195SShri Abhyankar for (i=0; i < event->nevents; i++) event->vtol[i] = vtol[i]; 120e3005195SShri Abhyankar } else { 121e3005195SShri Abhyankar if (tol != PETSC_DECIDE || tol != PETSC_DEFAULT) { 122e3005195SShri Abhyankar for (i=0; i < event->nevents; i++) event->vtol[i] = tol; 123e3005195SShri Abhyankar } 124e3005195SShri Abhyankar } 125e3005195SShri Abhyankar PetscFunctionReturn(0); 126e3005195SShri Abhyankar } 127e3005195SShri Abhyankar 1282dc7a7e3SShri Abhyankar /*@C 129ac6a796dSBarry Smith TSSetEventHandler - Sets a function used for detecting events 1302dc7a7e3SShri Abhyankar 1312dc7a7e3SShri Abhyankar Logically Collective on TS 1322dc7a7e3SShri Abhyankar 1332dc7a7e3SShri Abhyankar Input Parameters: 1342dc7a7e3SShri Abhyankar + ts - the TS context obtained from TSCreate() 1352dc7a7e3SShri Abhyankar . nevents - number of local events 136d94325d3SShri Abhyankar . direction - direction of zero crossing to be detected. -1 => Zero crossing in negative direction, 137d94325d3SShri Abhyankar +1 => Zero crossing in positive direction, 0 => both ways (one for each event) 138d94325d3SShri Abhyankar . terminate - flag to indicate whether time stepping should be terminated after 139d94325d3SShri Abhyankar event is detected (one for each event) 1406427ac75SLisandro Dalcin . eventhandler - event monitoring routine 1412dc7a7e3SShri Abhyankar . postevent - [optional] post-event function 1422589fa24SLisandro Dalcin - ctx - [optional] user-defined context for private data for the 1432dc7a7e3SShri Abhyankar event monitor and post event routine (use NULL if no 1442dc7a7e3SShri Abhyankar context is desired) 1452dc7a7e3SShri Abhyankar 1466427ac75SLisandro Dalcin Calling sequence of eventhandler: 1473a88037aSBarry Smith PetscErrorCode PetscEventHandler(TS ts,PetscReal t,Vec U,PetscScalar fvalue[],void* ctx) 1482dc7a7e3SShri Abhyankar 1492dc7a7e3SShri Abhyankar Input Parameters: 1502dc7a7e3SShri Abhyankar + ts - the TS context 1512dc7a7e3SShri Abhyankar . t - current time 1522dc7a7e3SShri Abhyankar . U - current iterate 1536427ac75SLisandro Dalcin - ctx - [optional] context passed with eventhandler 1542dc7a7e3SShri Abhyankar 1552dc7a7e3SShri Abhyankar Output parameters: 156d94325d3SShri Abhyankar . fvalue - function value of events at time t 1572dc7a7e3SShri Abhyankar 1582dc7a7e3SShri Abhyankar Calling sequence of postevent: 1592589fa24SLisandro Dalcin PetscErrorCode PostEvent(TS ts,PetscInt nevents_zero,PetscInt events_zero[],PetscReal t,Vec U,PetscBool forwardsolve,void* ctx) 1602dc7a7e3SShri Abhyankar 1612dc7a7e3SShri Abhyankar Input Parameters: 1622dc7a7e3SShri Abhyankar + ts - the TS context 1632dc7a7e3SShri Abhyankar . nevents_zero - number of local events whose event function is zero 1642dc7a7e3SShri Abhyankar . events_zero - indices of local events which have reached zero 1652dc7a7e3SShri Abhyankar . t - current time 1662dc7a7e3SShri Abhyankar . U - current solution 167031fbad4SShri Abhyankar . forwardsolve - Flag to indicate whether TS is doing a forward solve (1) or adjoint solve (0) 1686427ac75SLisandro Dalcin - ctx - the context passed with eventhandler 1692dc7a7e3SShri Abhyankar 1702dc7a7e3SShri Abhyankar Level: intermediate 1712dc7a7e3SShri Abhyankar 1722dc7a7e3SShri Abhyankar .seealso: TSCreate(), TSSetTimeStep(), TSSetConvergedReason() 1732dc7a7e3SShri Abhyankar @*/ 1742589fa24SLisandro Dalcin PetscErrorCode TSSetEventHandler(TS ts,PetscInt nevents,PetscInt direction[],PetscBool terminate[],PetscErrorCode (*eventhandler)(TS,PetscReal,Vec,PetscScalar[],void*),PetscErrorCode (*postevent)(TS,PetscInt,PetscInt[],PetscReal,Vec,PetscBool,void*),void *ctx) 1752dc7a7e3SShri Abhyankar { 1762dc7a7e3SShri Abhyankar PetscErrorCode ierr; 177*d294eb03SHong Zhang TSAdapt adapt; 178*d294eb03SHong Zhang PetscReal hmin; 1792dc7a7e3SShri Abhyankar TSEvent event; 180d94325d3SShri Abhyankar PetscInt i; 181006e6a18SShri Abhyankar PetscBool flg; 182a6c783d2SShri Abhyankar #if defined PETSC_USE_REAL_SINGLE 183a6c783d2SShri Abhyankar PetscReal tol=1e-4; 184a6c783d2SShri Abhyankar #else 185d569cc17SSatish Balay PetscReal tol=1e-6; 186a6c783d2SShri Abhyankar #endif 1872dc7a7e3SShri Abhyankar 1882dc7a7e3SShri Abhyankar PetscFunctionBegin; 1896427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1900a82b154SShri if (nevents) { 1916427ac75SLisandro Dalcin PetscValidIntPointer(direction,2); 1926427ac75SLisandro Dalcin PetscValidIntPointer(terminate,3); 1930a82b154SShri } 1946427ac75SLisandro Dalcin 1956427ac75SLisandro Dalcin ierr = PetscNewLog(ts,&event);CHKERRQ(ierr); 196854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->fvalue);CHKERRQ(ierr); 197854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->fvalue_prev);CHKERRQ(ierr); 198e2cdd850SShri Abhyankar ierr = PetscMalloc1(nevents,&event->fvalue_right);CHKERRQ(ierr); 199e2cdd850SShri Abhyankar ierr = PetscMalloc1(nevents,&event->zerocrossing);CHKERRQ(ierr); 200e2cdd850SShri Abhyankar ierr = PetscMalloc1(nevents,&event->side);CHKERRQ(ierr); 201854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->direction);CHKERRQ(ierr); 202854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->terminate);CHKERRQ(ierr); 203e3005195SShri Abhyankar ierr = PetscMalloc1(nevents,&event->vtol);CHKERRQ(ierr); 204d94325d3SShri Abhyankar for (i=0; i < nevents; i++) { 205d94325d3SShri Abhyankar event->direction[i] = direction[i]; 206d94325d3SShri Abhyankar event->terminate[i] = terminate[i]; 207e2cdd850SShri Abhyankar event->zerocrossing[i] = PETSC_FALSE; 208e2cdd850SShri Abhyankar event->side[i] = 0; 209d94325d3SShri Abhyankar } 210854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->events_zero);CHKERRQ(ierr); 2112589fa24SLisandro Dalcin event->nevents = nevents; 2126427ac75SLisandro Dalcin event->eventhandler = eventhandler; 2132dc7a7e3SShri Abhyankar event->postevent = postevent; 2146427ac75SLisandro Dalcin event->ctx = ctx; 215458122a4SShri Abhyankar event->timestep_posteventinterval = ts->time_step; 216*d294eb03SHong Zhang ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr); 217*d294eb03SHong Zhang ierr = TSAdaptGetStepLimits(adapt,&hmin,NULL);CHKERRQ(ierr); 218*d294eb03SHong Zhang event->timestep_min = hmin; 2192dc7a7e3SShri Abhyankar 22002749585SLisandro Dalcin event->recsize = 8; /* Initial size of the recorder */ 2215fbebc36SLisandro Dalcin ierr = PetscOptionsBegin(((PetscObject)ts)->comm,((PetscObject)ts)->prefix,"TS Event options","TS");CHKERRQ(ierr); 2222dc7a7e3SShri Abhyankar { 22302749585SLisandro Dalcin ierr = PetscOptionsReal("-ts_event_tol","Scalar event tolerance for zero crossing check","TSSetEventTolerances",tol,&tol,NULL);CHKERRQ(ierr); 224006e6a18SShri Abhyankar ierr = PetscOptionsName("-ts_event_monitor","Print choices made by event handler","",&flg);CHKERRQ(ierr); 225a4ffd976SShri Abhyankar ierr = PetscOptionsInt("-ts_event_recorder_initial_size","Initial size of event recorder","",event->recsize,&event->recsize,NULL);CHKERRQ(ierr); 226458122a4SShri Abhyankar ierr = PetscOptionsReal("-ts_event_post_eventinterval_step","Time step after event interval","",event->timestep_posteventinterval,&event->timestep_posteventinterval,NULL);CHKERRQ(ierr); 227*d294eb03SHong Zhang ierr = PetscOptionsReal("-ts_event_post_event_step","Time step after event","",event->timestep_postevent,&event->timestep_postevent,NULL);CHKERRQ(ierr); 228*d294eb03SHong Zhang ierr = PetscOptionsReal("-ts_event_dt_min","Minimum time step considered for TSEvent","",event->timestep_min,&event->timestep_min,NULL);CHKERRQ(ierr); 2292dc7a7e3SShri Abhyankar } 230b6518c14SStefano Zampini ierr = PetscOptionsEnd();CHKERRQ(ierr); 231a4ffd976SShri Abhyankar 232a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.time);CHKERRQ(ierr); 233a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.stepnum);CHKERRQ(ierr); 234a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.nevents);CHKERRQ(ierr); 235a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.eventidx);CHKERRQ(ierr); 236a4ffd976SShri Abhyankar for (i=0; i < event->recsize; i++) { 237a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->nevents,&event->recorder.eventidx[i]);CHKERRQ(ierr); 238a4ffd976SShri Abhyankar } 239e7069c78SShri /* Initialize the event recorder */ 240e7069c78SShri event->recorder.ctr = 0; 241a4ffd976SShri Abhyankar 242e3005195SShri Abhyankar for (i=0; i < event->nevents; i++) event->vtol[i] = tol; 2436427ac75SLisandro Dalcin if (flg) {ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,"stdout",&event->monitor);CHKERRQ(ierr);} 2449e12be75SShri Abhyankar 2456427ac75SLisandro Dalcin ierr = TSEventDestroy(&ts->event);CHKERRQ(ierr); 246d94325d3SShri Abhyankar ts->event = event; 247e7069c78SShri ts->event->refct = 1; 2482dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 2492dc7a7e3SShri Abhyankar } 2502dc7a7e3SShri Abhyankar 251a4ffd976SShri Abhyankar /* 252a4ffd976SShri Abhyankar TSEventRecorderResize - Resizes (2X) the event recorder arrays whenever the recording limit (event->recsize) 253a4ffd976SShri Abhyankar is reached. 254a4ffd976SShri Abhyankar */ 25502749585SLisandro Dalcin static PetscErrorCode TSEventRecorderResize(TSEvent event) 256a4ffd976SShri Abhyankar { 257a4ffd976SShri Abhyankar PetscErrorCode ierr; 258a4ffd976SShri Abhyankar PetscReal *time; 259a4ffd976SShri Abhyankar PetscInt *stepnum; 260a4ffd976SShri Abhyankar PetscInt *nevents; 261a4ffd976SShri Abhyankar PetscInt **eventidx; 262a4ffd976SShri Abhyankar PetscInt i,fact=2; 263a4ffd976SShri Abhyankar 264a4ffd976SShri Abhyankar PetscFunctionBegin; 265a4ffd976SShri Abhyankar 266a4ffd976SShri Abhyankar /* Create large arrays */ 267a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&time);CHKERRQ(ierr); 268a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&stepnum);CHKERRQ(ierr); 269a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&nevents);CHKERRQ(ierr); 270a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&eventidx);CHKERRQ(ierr); 271a4ffd976SShri Abhyankar for (i=0; i < fact*event->recsize; i++) { 272a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->nevents,&eventidx[i]);CHKERRQ(ierr); 273a4ffd976SShri Abhyankar } 274a4ffd976SShri Abhyankar 275a4ffd976SShri Abhyankar /* Copy over data */ 276580bdb30SBarry Smith ierr = PetscArraycpy(time,event->recorder.time,event->recsize);CHKERRQ(ierr); 277580bdb30SBarry Smith ierr = PetscArraycpy(stepnum,event->recorder.stepnum,event->recsize);CHKERRQ(ierr); 278580bdb30SBarry Smith ierr = PetscArraycpy(nevents,event->recorder.nevents,event->recsize);CHKERRQ(ierr); 279a4ffd976SShri Abhyankar for (i=0; i < event->recsize; i++) { 280580bdb30SBarry Smith ierr = PetscArraycpy(eventidx[i],event->recorder.eventidx[i],event->recorder.nevents[i]);CHKERRQ(ierr); 281a4ffd976SShri Abhyankar } 282a4ffd976SShri Abhyankar 283a4ffd976SShri Abhyankar /* Destroy old arrays */ 284a4ffd976SShri Abhyankar for (i=0; i < event->recsize; i++) { 285a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.eventidx[i]);CHKERRQ(ierr); 286a4ffd976SShri Abhyankar } 287a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.eventidx);CHKERRQ(ierr); 288a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.nevents);CHKERRQ(ierr); 289a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.stepnum);CHKERRQ(ierr); 290a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.time);CHKERRQ(ierr); 291a4ffd976SShri Abhyankar 292a4ffd976SShri Abhyankar /* Set pointers */ 293a4ffd976SShri Abhyankar event->recorder.time = time; 294a4ffd976SShri Abhyankar event->recorder.stepnum = stepnum; 295a4ffd976SShri Abhyankar event->recorder.nevents = nevents; 296a4ffd976SShri Abhyankar event->recorder.eventidx = eventidx; 297a4ffd976SShri Abhyankar 298a4ffd976SShri Abhyankar /* Double size */ 299a4ffd976SShri Abhyankar event->recsize *= fact; 300a4ffd976SShri Abhyankar 301a4ffd976SShri Abhyankar PetscFunctionReturn(0); 302a4ffd976SShri Abhyankar } 303a4ffd976SShri Abhyankar 304031fbad4SShri Abhyankar /* 305ac6a796dSBarry Smith Helper routine to handle user postevents and recording 306031fbad4SShri Abhyankar */ 3074597913aSLisandro Dalcin static PetscErrorCode TSPostEvent(TS ts,PetscReal t,Vec U) 3082dc7a7e3SShri Abhyankar { 3092dc7a7e3SShri Abhyankar PetscErrorCode ierr; 3102dc7a7e3SShri Abhyankar TSEvent event = ts->event; 3112dc7a7e3SShri Abhyankar PetscBool terminate = PETSC_FALSE; 31228d5b5d6SLisandro Dalcin PetscBool restart = PETSC_FALSE; 313d0578d90SShri Abhyankar PetscInt i,ctr,stepnum; 3147324a0ffSLisandro Dalcin PetscBool inflag[2],outflag[2]; 3154597913aSLisandro Dalcin PetscBool forwardsolve = PETSC_TRUE; /* Flag indicating that TS is doing a forward solve */ 3162dc7a7e3SShri Abhyankar 3172dc7a7e3SShri Abhyankar PetscFunctionBegin; 3182dc7a7e3SShri Abhyankar if (event->postevent) { 31928d5b5d6SLisandro Dalcin PetscObjectState state_prev,state_post; 32028d5b5d6SLisandro Dalcin ierr = PetscObjectStateGet((PetscObject)U,&state_prev);CHKERRQ(ierr); 3214597913aSLisandro Dalcin ierr = (*event->postevent)(ts,event->nevents_zero,event->events_zero,t,U,forwardsolve,event->ctx);CHKERRQ(ierr); 32228d5b5d6SLisandro Dalcin ierr = PetscObjectStateGet((PetscObject)U,&state_post);CHKERRQ(ierr); 32328d5b5d6SLisandro Dalcin if (state_prev != state_post) restart = PETSC_TRUE; 3242dc7a7e3SShri Abhyankar } 3254597913aSLisandro Dalcin 32628d5b5d6SLisandro Dalcin /* Handle termination events and step restart */ 32728d5b5d6SLisandro Dalcin for (i=0; i<event->nevents_zero; i++) if (event->terminate[event->events_zero[i]]) terminate = PETSC_TRUE; 3287324a0ffSLisandro Dalcin inflag[0] = restart; inflag[1] = terminate; 3297324a0ffSLisandro Dalcin ierr = MPIU_Allreduce(inflag,outflag,2,MPIU_BOOL,MPI_LOR,((PetscObject)ts)->comm);CHKERRQ(ierr); 3307324a0ffSLisandro Dalcin restart = outflag[0]; terminate = outflag[1]; 3317324a0ffSLisandro Dalcin if (restart) {ierr = TSRestartStep(ts);CHKERRQ(ierr);} 3327324a0ffSLisandro Dalcin if (terminate) {ierr = TSSetConvergedReason(ts,TS_CONVERGED_EVENT);CHKERRQ(ierr);} 3337324a0ffSLisandro Dalcin event->status = terminate ? TSEVENT_NONE : TSEVENT_RESET_NEXTSTEP; 334f7aea88cSShri Abhyankar 3354597913aSLisandro Dalcin /* Reset event residual functions as states might get changed by the postevent callback */ 336f443add6SLisandro Dalcin if (event->postevent) { 3378860a134SJunchao Zhang ierr = VecLockReadPush(U);CHKERRQ(ierr); 338f443add6SLisandro Dalcin ierr = (*event->eventhandler)(ts,t,U,event->fvalue,event->ctx);CHKERRQ(ierr); 3398860a134SJunchao Zhang ierr = VecLockReadPop(U);CHKERRQ(ierr); 340f443add6SLisandro Dalcin } 341f443add6SLisandro Dalcin 342f443add6SLisandro Dalcin /* Cache current time and event residual functions */ 343f443add6SLisandro Dalcin event->ptime_prev = t; 344f443add6SLisandro Dalcin for (i=0; i<event->nevents; i++) 345f443add6SLisandro Dalcin event->fvalue_prev[i] = event->fvalue[i]; 3464597913aSLisandro Dalcin 347d0578d90SShri Abhyankar /* Record the event in the event recorder */ 34880275a0aSLisandro Dalcin ierr = TSGetStepNumber(ts,&stepnum);CHKERRQ(ierr); 349f7aea88cSShri Abhyankar ctr = event->recorder.ctr; 350a4ffd976SShri Abhyankar if (ctr == event->recsize) { 351a4ffd976SShri Abhyankar ierr = TSEventRecorderResize(event);CHKERRQ(ierr); 352a4ffd976SShri Abhyankar } 353f7aea88cSShri Abhyankar event->recorder.time[ctr] = t; 354d0578d90SShri Abhyankar event->recorder.stepnum[ctr] = stepnum; 3554597913aSLisandro Dalcin event->recorder.nevents[ctr] = event->nevents_zero; 3564597913aSLisandro Dalcin for (i=0; i<event->nevents_zero; i++) event->recorder.eventidx[ctr][i] = event->events_zero[i]; 357f7aea88cSShri Abhyankar event->recorder.ctr++; 3582dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 3592dc7a7e3SShri Abhyankar } 3602dc7a7e3SShri Abhyankar 36102749585SLisandro Dalcin /* Uses Anderson-Bjorck variant of regula falsi method */ 362a3a8645aSShri Abhyankar PETSC_STATIC_INLINE PetscReal TSEventComputeStepSize(PetscReal tleft,PetscReal t,PetscReal tright,PetscScalar fleft,PetscScalar f,PetscScalar fright,PetscInt side,PetscReal dt) 36338bf2713SShri Abhyankar { 36402749585SLisandro Dalcin PetscReal new_dt, scal = 1.0; 365e2cdd850SShri Abhyankar if (PetscRealPart(fleft)*PetscRealPart(f) < 0) { 366e2cdd850SShri Abhyankar if (side == 1) { 367a6c783d2SShri Abhyankar scal = (PetscRealPart(fright) - PetscRealPart(f))/PetscRealPart(fright); 368a6c783d2SShri Abhyankar if (scal < PETSC_SMALL) scal = 0.5; 369e2cdd850SShri Abhyankar } 37002749585SLisandro Dalcin new_dt = (scal*PetscRealPart(fleft)*t - PetscRealPart(f)*tleft)/(scal*PetscRealPart(fleft) - PetscRealPart(f)) - tleft; 371e2cdd850SShri Abhyankar } else { 372e2cdd850SShri Abhyankar if (side == -1) { 373a6c783d2SShri Abhyankar scal = (PetscRealPart(fleft) - PetscRealPart(f))/PetscRealPart(fleft); 374a6c783d2SShri Abhyankar if (scal < PETSC_SMALL) scal = 0.5; 375e2cdd850SShri Abhyankar } 37602749585SLisandro Dalcin new_dt = (PetscRealPart(f)*tright - scal*PetscRealPart(fright)*t)/(PetscRealPart(f) - scal*PetscRealPart(fright)) - t; 377e2cdd850SShri Abhyankar } 37802749585SLisandro Dalcin return PetscMin(dt,new_dt); 37938bf2713SShri Abhyankar } 380e2cdd850SShri Abhyankar 381*d294eb03SHong Zhang static PetscErrorCode TSEventDetection(TS ts) 382*d294eb03SHong Zhang { 383*d294eb03SHong Zhang PetscErrorCode ierr; 384*d294eb03SHong Zhang TSEvent event = ts->event; 385*d294eb03SHong Zhang PetscReal t; 386*d294eb03SHong Zhang PetscInt i; 387*d294eb03SHong Zhang PetscInt rollback=0,in[2],out[2]; 388*d294eb03SHong Zhang PetscInt fvalue_sign,fvalueprev_sign; 389*d294eb03SHong Zhang 390*d294eb03SHong Zhang PetscFunctionBegin; 391*d294eb03SHong Zhang ierr = TSGetTime(ts,&t);CHKERRQ(ierr); 392*d294eb03SHong Zhang for (i=0; i < event->nevents; i++) { 393*d294eb03SHong Zhang if (PetscAbsScalar(event->fvalue[i]) < event->vtol[i]) { 394*d294eb03SHong Zhang if (!event->iterctr) event->zerocrossing[i] = PETSC_TRUE; 395*d294eb03SHong Zhang event->status = TSEVENT_LOCATED_INTERVAL; 396*d294eb03SHong Zhang if (event->monitor) { 397*d294eb03SHong Zhang ierr = PetscViewerASCIIPrintf(event->monitor,"TSEvent: iter %D - Event %D interval detected [%g - %g]\n",event->iterctr,i,(double)event->ptime_prev,(double)t);CHKERRQ(ierr); 398*d294eb03SHong Zhang } 399*d294eb03SHong Zhang continue; 400*d294eb03SHong Zhang } 401*d294eb03SHong Zhang fvalue_sign = PetscSign(PetscRealPart(event->fvalue[i])); 402*d294eb03SHong Zhang fvalueprev_sign = PetscSign(PetscRealPart(event->fvalue_prev[i])); 403*d294eb03SHong Zhang if (fvalueprev_sign != 0 && (fvalue_sign != fvalueprev_sign)) { 404*d294eb03SHong Zhang rollback = 1; 405*d294eb03SHong Zhang if (!event->iterctr) event->zerocrossing[i] = PETSC_TRUE; 406*d294eb03SHong Zhang event->status = TSEVENT_LOCATED_INTERVAL; 407*d294eb03SHong Zhang if (event->monitor) { 408*d294eb03SHong Zhang ierr = PetscViewerASCIIPrintf(event->monitor,"TSEvent: iter %D - Event %D interval detected [%g - %g]\n",event->iterctr,i,(double)event->ptime_prev,(double)t);CHKERRQ(ierr); 409*d294eb03SHong Zhang } 410*d294eb03SHong Zhang } 411*d294eb03SHong Zhang } 412*d294eb03SHong Zhang in[0] = event->status; in[1] = rollback; 413*d294eb03SHong Zhang ierr = MPIU_Allreduce(in,out,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr); 414*d294eb03SHong Zhang event->status = (TSEventStatus)out[0]; rollback = out[1]; 415*d294eb03SHong Zhang if (rollback) event->status = TSEVENT_LOCATED_INTERVAL; 416*d294eb03SHong Zhang PetscFunctionReturn(0); 417*d294eb03SHong Zhang } 418*d294eb03SHong Zhang 419*d294eb03SHong Zhang static PetscErrorCode TSEventLocation(TS ts,PetscReal *dt) 420*d294eb03SHong Zhang { 421*d294eb03SHong Zhang PetscErrorCode ierr; 422*d294eb03SHong Zhang TSEvent event = ts->event; 423*d294eb03SHong Zhang PetscInt i; 424*d294eb03SHong Zhang PetscReal t; 425*d294eb03SHong Zhang PetscInt fvalue_sign; 426*d294eb03SHong Zhang PetscInt in,out; 427*d294eb03SHong Zhang 428*d294eb03SHong Zhang PetscFunctionBegin; 429*d294eb03SHong Zhang ierr = TSGetTime(ts,&t);CHKERRQ(ierr); 430*d294eb03SHong Zhang event->nevents_zero = 0; 431*d294eb03SHong Zhang for (i=0; i < event->nevents; i++) { 432*d294eb03SHong Zhang if (event->zerocrossing[i]) { 433*d294eb03SHong Zhang if (PetscAbsScalar(event->fvalue[i]) < event->vtol[i] || *dt < event->timestep_min || PetscAbsReal((*dt)/((event->ptime_right-event->ptime_prev)/2)) < event->vtol[i]) { /* stopping criteria */ 434*d294eb03SHong Zhang event->status = TSEVENT_ZERO; 435*d294eb03SHong Zhang event->fvalue_right[i] = event->fvalue[i]; 436*d294eb03SHong Zhang event->events_zero[event->nevents_zero++] = i; 437*d294eb03SHong Zhang if (event->monitor) { 438*d294eb03SHong Zhang ierr = PetscViewerASCIIPrintf(event->monitor,"TSEvent: Event %D zero crossing at time %g located in %D iterations\n",i,(double)t,event->iterctr);CHKERRQ(ierr); 439*d294eb03SHong Zhang } 440*d294eb03SHong Zhang event->zerocrossing[i] = PETSC_FALSE; 441*d294eb03SHong Zhang continue; 442*d294eb03SHong Zhang } 443*d294eb03SHong Zhang /* Compute new time step */ 444*d294eb03SHong Zhang *dt = TSEventComputeStepSize(event->ptime_prev,t,event->ptime_right,event->fvalue_prev[i],event->fvalue[i],event->fvalue_right[i],event->side[i],*dt); 445*d294eb03SHong Zhang if (event->status == TSEVENT_LOCATED_INTERVAL) { 446*d294eb03SHong Zhang fvalue_sign = PetscSign(PetscRealPart(event->fvalue[i])); 447*d294eb03SHong Zhang switch (event->direction[i]) { 448*d294eb03SHong Zhang case -1: 449*d294eb03SHong Zhang if (fvalue_sign < 0) { 450*d294eb03SHong Zhang event->fvalue_right[i] = event->fvalue[i]; 451*d294eb03SHong Zhang event->side[i] = 1; 452*d294eb03SHong Zhang } 453*d294eb03SHong Zhang break; 454*d294eb03SHong Zhang case 1: 455*d294eb03SHong Zhang if (fvalue_sign > 0) { 456*d294eb03SHong Zhang event->fvalue_right[i] = event->fvalue[i]; 457*d294eb03SHong Zhang event->side[i] = 1; 458*d294eb03SHong Zhang } 459*d294eb03SHong Zhang break; 460*d294eb03SHong Zhang case 0: 461*d294eb03SHong Zhang event->fvalue_right[i] = event->fvalue[i]; 462*d294eb03SHong Zhang event->side[i] = 1; 463*d294eb03SHong Zhang break; 464*d294eb03SHong Zhang } 465*d294eb03SHong Zhang } 466*d294eb03SHong Zhang if (event->status == TSEVENT_PROCESSING) { 467*d294eb03SHong Zhang event->fvalue_prev[i] = event->fvalue[i]; 468*d294eb03SHong Zhang event->side[i] = -1; 469*d294eb03SHong Zhang } 470*d294eb03SHong Zhang } 471*d294eb03SHong Zhang } 472*d294eb03SHong Zhang in = event->status; 473*d294eb03SHong Zhang ierr = MPIU_Allreduce(&in,&out,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr); 474*d294eb03SHong Zhang event->status = (TSEventStatus)out; 475*d294eb03SHong Zhang if (event->status == TSEVENT_ZERO) { 476*d294eb03SHong Zhang for (i=0; i<event->nevents; i++) event->side[i] = 0; 477*d294eb03SHong Zhang } 478*d294eb03SHong Zhang PetscFunctionReturn(0); 479*d294eb03SHong Zhang } 48038bf2713SShri Abhyankar 4816427ac75SLisandro Dalcin PetscErrorCode TSEventHandler(TS ts) 4822dc7a7e3SShri Abhyankar { 4832dc7a7e3SShri Abhyankar PetscErrorCode ierr; 4846427ac75SLisandro Dalcin TSEvent event; 4852dc7a7e3SShri Abhyankar PetscReal t; 4862dc7a7e3SShri Abhyankar Vec U; 4872dc7a7e3SShri Abhyankar PetscInt i; 4887dbe0728SLisandro Dalcin PetscReal dt,dt_min; 4892dc7a7e3SShri Abhyankar 4902dc7a7e3SShri Abhyankar PetscFunctionBegin; 4916427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 4926427ac75SLisandro Dalcin if (!ts->event) PetscFunctionReturn(0); 4936427ac75SLisandro Dalcin event = ts->event; 4942dc7a7e3SShri Abhyankar 4952dc7a7e3SShri Abhyankar ierr = TSGetTime(ts,&t);CHKERRQ(ierr); 4967dbe0728SLisandro Dalcin ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr); 4972dc7a7e3SShri Abhyankar ierr = TSGetSolution(ts,&U);CHKERRQ(ierr); 4982dc7a7e3SShri Abhyankar 4997dbe0728SLisandro Dalcin if (event->status == TSEVENT_NONE) { 5007dbe0728SLisandro Dalcin event->timestep_prev = dt; 501*d294eb03SHong Zhang event->ptime_end = t; 5027dbe0728SLisandro Dalcin } 5032dc7a7e3SShri Abhyankar if (event->status == TSEVENT_RESET_NEXTSTEP) { 504*d294eb03SHong Zhang /* user has specified a PostEventInterval dt */ 505458122a4SShri Abhyankar dt = event->timestep_posteventinterval; 506e97c63d7SStefano Zampini if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 507e97c63d7SStefano Zampini PetscReal maxdt = ts->max_time-t; 508e97c63d7SStefano Zampini dt = dt > maxdt ? maxdt : (PetscIsCloseAtTol(dt,maxdt,10*PETSC_MACHINE_EPSILON,0) ? maxdt : dt); 509e97c63d7SStefano Zampini } 5107dbe0728SLisandro Dalcin ierr = TSSetTimeStep(ts,dt);CHKERRQ(ierr); 5112dc7a7e3SShri Abhyankar event->status = TSEVENT_NONE; 5122dc7a7e3SShri Abhyankar } 5132dc7a7e3SShri Abhyankar 5148860a134SJunchao Zhang ierr = VecLockReadPush(U);CHKERRQ(ierr); 5156427ac75SLisandro Dalcin ierr = (*event->eventhandler)(ts,t,U,event->fvalue,event->ctx);CHKERRQ(ierr); 5168860a134SJunchao Zhang ierr = VecLockReadPop(U);CHKERRQ(ierr); 5179e12be75SShri Abhyankar 518*d294eb03SHong Zhang /* Detect the events */ 519*d294eb03SHong Zhang ierr = TSEventDetection(ts);CHKERRQ(ierr); 520*d294eb03SHong Zhang 521*d294eb03SHong Zhang /* Locate the events */ 522*d294eb03SHong Zhang if (event->status == TSEVENT_LOCATED_INTERVAL || event->status == TSEVENT_PROCESSING) { 523*d294eb03SHong Zhang /* Approach the zero crosing by setting a new step size */ 524*d294eb03SHong Zhang ierr = TSEventLocation(ts,&dt);CHKERRQ(ierr); 525*d294eb03SHong Zhang /* Roll back when new events are detected */ 526*d294eb03SHong Zhang if (event->status == TSEVENT_LOCATED_INTERVAL) { 527*d294eb03SHong Zhang ierr = TSRollBack(ts);CHKERRQ(ierr); 528*d294eb03SHong Zhang ierr = TSSetConvergedReason(ts,TS_CONVERGED_ITERATING);CHKERRQ(ierr); 529*d294eb03SHong Zhang event->iterctr++; 530006e6a18SShri Abhyankar } 531*d294eb03SHong Zhang ierr = MPIU_Allreduce(&dt,&dt_min,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr); 532*d294eb03SHong Zhang ierr = TSSetTimeStep(ts,dt_min);CHKERRQ(ierr); 533e2cdd850SShri Abhyankar 534*d294eb03SHong Zhang /* Found the zero crossing */ 5359e12be75SShri Abhyankar if (event->status == TSEVENT_ZERO) { 5364597913aSLisandro Dalcin ierr = TSPostEvent(ts,t,U);CHKERRQ(ierr); 5379e12be75SShri Abhyankar 538e2cdd850SShri Abhyankar dt = event->ptime_end - t; 539ad508104SStefano Zampini if (PetscAbsReal(dt) < PETSC_SMALL) { /* we hit the event, continue with the candidate time step */ 540ad508104SStefano Zampini dt = event->timestep_prev; 541ad508104SStefano Zampini event->status = TSEVENT_NONE; 542ad508104SStefano Zampini } 543*d294eb03SHong Zhang if (event->timestep_postevent) { /* user has specified a PostEvent dt*/ 544*d294eb03SHong Zhang dt = event->timestep_postevent; 545*d294eb03SHong Zhang } 546e97c63d7SStefano Zampini if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 547e97c63d7SStefano Zampini PetscReal maxdt = ts->max_time-t; 548e97c63d7SStefano Zampini dt = dt > maxdt ? maxdt : (PetscIsCloseAtTol(dt,maxdt,10*PETSC_MACHINE_EPSILON,0) ? maxdt : dt); 549e97c63d7SStefano Zampini } 5509e12be75SShri Abhyankar ierr = TSSetTimeStep(ts,dt);CHKERRQ(ierr); 55138bf2713SShri Abhyankar event->iterctr = 0; 5529e12be75SShri Abhyankar } 553*d294eb03SHong Zhang /* Have not found the zero crosing yet */ 554*d294eb03SHong Zhang if (event->status == TSEVENT_PROCESSING) { 555*d294eb03SHong Zhang if (event->monitor) { 556*d294eb03SHong Zhang ierr = PetscViewerASCIIPrintf(event->monitor,"TSEvent: iter %D - Stepping forward as no event detected in interval [%g - %g]\n",event->iterctr,(double)event->ptime_prev,(double)t);CHKERRQ(ierr); 557*d294eb03SHong Zhang } 558*d294eb03SHong Zhang event->iterctr++; 559*d294eb03SHong Zhang } 560*d294eb03SHong Zhang } 561*d294eb03SHong Zhang if (event->status == TSEVENT_LOCATED_INTERVAL) { /* The step has been rolled back */ 5622dc7a7e3SShri Abhyankar event->status = TSEVENT_PROCESSING; 563e2cdd850SShri Abhyankar event->ptime_right = t; 5642dc7a7e3SShri Abhyankar } else { 565*d294eb03SHong Zhang for (i=0; i < event->nevents; i++) event->fvalue_prev[i] = event->fvalue[i]; 56638bf2713SShri Abhyankar event->ptime_prev = t; 56738bf2713SShri Abhyankar } 5682dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 5692dc7a7e3SShri Abhyankar } 5702dc7a7e3SShri Abhyankar 5716427ac75SLisandro Dalcin PetscErrorCode TSAdjointEventHandler(TS ts) 572d0578d90SShri Abhyankar { 573d0578d90SShri Abhyankar PetscErrorCode ierr; 5746427ac75SLisandro Dalcin TSEvent event; 575d0578d90SShri Abhyankar PetscReal t; 576d0578d90SShri Abhyankar Vec U; 577d0578d90SShri Abhyankar PetscInt ctr; 578d0578d90SShri Abhyankar PetscBool forwardsolve=PETSC_FALSE; /* Flag indicating that TS is doing an adjoint solve */ 579d0578d90SShri Abhyankar 580d0578d90SShri Abhyankar PetscFunctionBegin; 5816427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 5826427ac75SLisandro Dalcin if (!ts->event) PetscFunctionReturn(0); 5836427ac75SLisandro Dalcin event = ts->event; 584d0578d90SShri Abhyankar 585d0578d90SShri Abhyankar ierr = TSGetTime(ts,&t);CHKERRQ(ierr); 586d0578d90SShri Abhyankar ierr = TSGetSolution(ts,&U);CHKERRQ(ierr); 587d0578d90SShri Abhyankar 588d0578d90SShri Abhyankar ctr = event->recorder.ctr-1; 589bcbf8bb3SShri Abhyankar if (ctr >= 0 && PetscAbsReal(t - event->recorder.time[ctr]) < PETSC_SMALL) { 590d0578d90SShri Abhyankar /* Call the user postevent function */ 591d0578d90SShri Abhyankar if (event->postevent) { 5926427ac75SLisandro Dalcin ierr = (*event->postevent)(ts,event->recorder.nevents[ctr],event->recorder.eventidx[ctr],t,U,forwardsolve,event->ctx);CHKERRQ(ierr); 593d0578d90SShri Abhyankar event->recorder.ctr--; 594d0578d90SShri Abhyankar } 595d0578d90SShri Abhyankar } 596d0578d90SShri Abhyankar 597d0578d90SShri Abhyankar PetscBarrier((PetscObject)ts); 598d0578d90SShri Abhyankar PetscFunctionReturn(0); 599d0578d90SShri Abhyankar } 6001ea83e56SMiguel 6011ea83e56SMiguel /*@ 6021ea83e56SMiguel TSGetNumEvents - Get the numbers of events set 6031ea83e56SMiguel 6041ea83e56SMiguel Logically Collective 6051ea83e56SMiguel 6061ea83e56SMiguel Input Argument: 6071ea83e56SMiguel + ts - the TS context 6081ea83e56SMiguel 6091ea83e56SMiguel Output Argument: 6101ea83e56SMiguel . nevents - number of events 6111ea83e56SMiguel 6121ea83e56SMiguel Level: intermediate 6131ea83e56SMiguel 6141ea83e56SMiguel .seealso: TSSetEventHandler() 6151ea83e56SMiguel 6161ea83e56SMiguel @*/ 6171ea83e56SMiguel PetscErrorCode TSGetNumEvents(TS ts,PetscInt * nevents) 6181ea83e56SMiguel { 6191ea83e56SMiguel PetscFunctionBegin; 6201ea83e56SMiguel *nevents = ts->event->nevents; 6211ea83e56SMiguel PetscFunctionReturn(0); 6221ea83e56SMiguel } 623