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); 29e7069c78SShri if (--(*event)->refct > 0) {*event = 0; 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; 1772dc7a7e3SShri Abhyankar TSEvent event; 178d94325d3SShri Abhyankar PetscInt i; 179006e6a18SShri Abhyankar PetscBool flg; 180a6c783d2SShri Abhyankar #if defined PETSC_USE_REAL_SINGLE 181a6c783d2SShri Abhyankar PetscReal tol=1e-4; 182a6c783d2SShri Abhyankar #else 183d569cc17SSatish Balay PetscReal tol=1e-6; 184a6c783d2SShri Abhyankar #endif 1852dc7a7e3SShri Abhyankar 1862dc7a7e3SShri Abhyankar PetscFunctionBegin; 1876427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1880a82b154SShri if (nevents) { 1896427ac75SLisandro Dalcin PetscValidIntPointer(direction,2); 1906427ac75SLisandro Dalcin PetscValidIntPointer(terminate,3); 1910a82b154SShri } 1926427ac75SLisandro Dalcin 1936427ac75SLisandro Dalcin ierr = PetscNewLog(ts,&event);CHKERRQ(ierr); 194854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->fvalue);CHKERRQ(ierr); 195854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->fvalue_prev);CHKERRQ(ierr); 196e2cdd850SShri Abhyankar ierr = PetscMalloc1(nevents,&event->fvalue_right);CHKERRQ(ierr); 197e2cdd850SShri Abhyankar ierr = PetscMalloc1(nevents,&event->zerocrossing);CHKERRQ(ierr); 198e2cdd850SShri Abhyankar ierr = PetscMalloc1(nevents,&event->side);CHKERRQ(ierr); 199854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->direction);CHKERRQ(ierr); 200854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->terminate);CHKERRQ(ierr); 201e3005195SShri Abhyankar ierr = PetscMalloc1(nevents,&event->vtol);CHKERRQ(ierr); 202d94325d3SShri Abhyankar for (i=0; i < nevents; i++) { 203d94325d3SShri Abhyankar event->direction[i] = direction[i]; 204d94325d3SShri Abhyankar event->terminate[i] = terminate[i]; 205e2cdd850SShri Abhyankar event->zerocrossing[i] = PETSC_FALSE; 206e2cdd850SShri Abhyankar event->side[i] = 0; 207d94325d3SShri Abhyankar } 208854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->events_zero);CHKERRQ(ierr); 2092589fa24SLisandro Dalcin event->nevents = nevents; 2106427ac75SLisandro Dalcin event->eventhandler = eventhandler; 2112dc7a7e3SShri Abhyankar event->postevent = postevent; 2126427ac75SLisandro Dalcin event->ctx = ctx; 213458122a4SShri Abhyankar event->timestep_posteventinterval = ts->time_step; 2142dc7a7e3SShri Abhyankar 21502749585SLisandro Dalcin event->recsize = 8; /* Initial size of the recorder */ 2165fbebc36SLisandro Dalcin ierr = PetscOptionsBegin(((PetscObject)ts)->comm,((PetscObject)ts)->prefix,"TS Event options","TS");CHKERRQ(ierr); 2172dc7a7e3SShri Abhyankar { 21802749585SLisandro Dalcin ierr = PetscOptionsReal("-ts_event_tol","Scalar event tolerance for zero crossing check","TSSetEventTolerances",tol,&tol,NULL);CHKERRQ(ierr); 219006e6a18SShri Abhyankar ierr = PetscOptionsName("-ts_event_monitor","Print choices made by event handler","",&flg);CHKERRQ(ierr); 220a4ffd976SShri Abhyankar ierr = PetscOptionsInt("-ts_event_recorder_initial_size","Initial size of event recorder","",event->recsize,&event->recsize,NULL);CHKERRQ(ierr); 221458122a4SShri Abhyankar ierr = PetscOptionsReal("-ts_event_post_eventinterval_step","Time step after event interval","",event->timestep_posteventinterval,&event->timestep_posteventinterval,NULL);CHKERRQ(ierr); 2222dc7a7e3SShri Abhyankar } 223b6518c14SStefano Zampini ierr = PetscOptionsEnd();CHKERRQ(ierr); 224a4ffd976SShri Abhyankar 225a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.time);CHKERRQ(ierr); 226a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.stepnum);CHKERRQ(ierr); 227a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.nevents);CHKERRQ(ierr); 228a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.eventidx);CHKERRQ(ierr); 229a4ffd976SShri Abhyankar for (i=0; i < event->recsize; i++) { 230a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->nevents,&event->recorder.eventidx[i]);CHKERRQ(ierr); 231a4ffd976SShri Abhyankar } 232e7069c78SShri /* Initialize the event recorder */ 233e7069c78SShri event->recorder.ctr = 0; 234a4ffd976SShri Abhyankar 235e3005195SShri Abhyankar for (i=0; i < event->nevents; i++) event->vtol[i] = tol; 2366427ac75SLisandro Dalcin if (flg) {ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,"stdout",&event->monitor);CHKERRQ(ierr);} 2379e12be75SShri Abhyankar 2386427ac75SLisandro Dalcin ierr = TSEventDestroy(&ts->event);CHKERRQ(ierr); 239d94325d3SShri Abhyankar ts->event = event; 240e7069c78SShri ts->event->refct = 1; 2412dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 2422dc7a7e3SShri Abhyankar } 2432dc7a7e3SShri Abhyankar 244a4ffd976SShri Abhyankar /* 245a4ffd976SShri Abhyankar TSEventRecorderResize - Resizes (2X) the event recorder arrays whenever the recording limit (event->recsize) 246a4ffd976SShri Abhyankar is reached. 247a4ffd976SShri Abhyankar */ 24802749585SLisandro Dalcin static PetscErrorCode TSEventRecorderResize(TSEvent event) 249a4ffd976SShri Abhyankar { 250a4ffd976SShri Abhyankar PetscErrorCode ierr; 251a4ffd976SShri Abhyankar PetscReal *time; 252a4ffd976SShri Abhyankar PetscInt *stepnum; 253a4ffd976SShri Abhyankar PetscInt *nevents; 254a4ffd976SShri Abhyankar PetscInt **eventidx; 255a4ffd976SShri Abhyankar PetscInt i,fact=2; 256a4ffd976SShri Abhyankar 257a4ffd976SShri Abhyankar PetscFunctionBegin; 258a4ffd976SShri Abhyankar 259a4ffd976SShri Abhyankar /* Create large arrays */ 260a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&time);CHKERRQ(ierr); 261a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&stepnum);CHKERRQ(ierr); 262a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&nevents);CHKERRQ(ierr); 263a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&eventidx);CHKERRQ(ierr); 264a4ffd976SShri Abhyankar for (i=0; i < fact*event->recsize; i++) { 265a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->nevents,&eventidx[i]);CHKERRQ(ierr); 266a4ffd976SShri Abhyankar } 267a4ffd976SShri Abhyankar 268a4ffd976SShri Abhyankar /* Copy over data */ 269580bdb30SBarry Smith ierr = PetscArraycpy(time,event->recorder.time,event->recsize);CHKERRQ(ierr); 270580bdb30SBarry Smith ierr = PetscArraycpy(stepnum,event->recorder.stepnum,event->recsize);CHKERRQ(ierr); 271580bdb30SBarry Smith ierr = PetscArraycpy(nevents,event->recorder.nevents,event->recsize);CHKERRQ(ierr); 272a4ffd976SShri Abhyankar for (i=0; i < event->recsize; i++) { 273580bdb30SBarry Smith ierr = PetscArraycpy(eventidx[i],event->recorder.eventidx[i],event->recorder.nevents[i]);CHKERRQ(ierr); 274a4ffd976SShri Abhyankar } 275a4ffd976SShri Abhyankar 276a4ffd976SShri Abhyankar /* Destroy old arrays */ 277a4ffd976SShri Abhyankar for (i=0; i < event->recsize; i++) { 278a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.eventidx[i]);CHKERRQ(ierr); 279a4ffd976SShri Abhyankar } 280a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.eventidx);CHKERRQ(ierr); 281a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.nevents);CHKERRQ(ierr); 282a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.stepnum);CHKERRQ(ierr); 283a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.time);CHKERRQ(ierr); 284a4ffd976SShri Abhyankar 285a4ffd976SShri Abhyankar /* Set pointers */ 286a4ffd976SShri Abhyankar event->recorder.time = time; 287a4ffd976SShri Abhyankar event->recorder.stepnum = stepnum; 288a4ffd976SShri Abhyankar event->recorder.nevents = nevents; 289a4ffd976SShri Abhyankar event->recorder.eventidx = eventidx; 290a4ffd976SShri Abhyankar 291a4ffd976SShri Abhyankar /* Double size */ 292a4ffd976SShri Abhyankar event->recsize *= fact; 293a4ffd976SShri Abhyankar 294a4ffd976SShri Abhyankar PetscFunctionReturn(0); 295a4ffd976SShri Abhyankar } 296a4ffd976SShri Abhyankar 297031fbad4SShri Abhyankar /* 298ac6a796dSBarry Smith Helper routine to handle user postevents and recording 299031fbad4SShri Abhyankar */ 3004597913aSLisandro Dalcin static PetscErrorCode TSPostEvent(TS ts,PetscReal t,Vec U) 3012dc7a7e3SShri Abhyankar { 3022dc7a7e3SShri Abhyankar PetscErrorCode ierr; 3032dc7a7e3SShri Abhyankar TSEvent event = ts->event; 3042dc7a7e3SShri Abhyankar PetscBool terminate = PETSC_FALSE; 30528d5b5d6SLisandro Dalcin PetscBool restart = PETSC_FALSE; 306d0578d90SShri Abhyankar PetscInt i,ctr,stepnum; 3077324a0ffSLisandro Dalcin PetscBool inflag[2],outflag[2]; 3084597913aSLisandro Dalcin PetscBool forwardsolve = PETSC_TRUE; /* Flag indicating that TS is doing a forward solve */ 3092dc7a7e3SShri Abhyankar 3102dc7a7e3SShri Abhyankar PetscFunctionBegin; 3112dc7a7e3SShri Abhyankar if (event->postevent) { 31228d5b5d6SLisandro Dalcin PetscObjectState state_prev,state_post; 31328d5b5d6SLisandro Dalcin ierr = PetscObjectStateGet((PetscObject)U,&state_prev);CHKERRQ(ierr); 3144597913aSLisandro Dalcin ierr = (*event->postevent)(ts,event->nevents_zero,event->events_zero,t,U,forwardsolve,event->ctx);CHKERRQ(ierr); 31528d5b5d6SLisandro Dalcin ierr = PetscObjectStateGet((PetscObject)U,&state_post);CHKERRQ(ierr); 31628d5b5d6SLisandro Dalcin if (state_prev != state_post) restart = PETSC_TRUE; 3172dc7a7e3SShri Abhyankar } 3184597913aSLisandro Dalcin 31928d5b5d6SLisandro Dalcin /* Handle termination events and step restart */ 32028d5b5d6SLisandro Dalcin for (i=0; i<event->nevents_zero; i++) if (event->terminate[event->events_zero[i]]) terminate = PETSC_TRUE; 3217324a0ffSLisandro Dalcin inflag[0] = restart; inflag[1] = terminate; 3227324a0ffSLisandro Dalcin ierr = MPIU_Allreduce(inflag,outflag,2,MPIU_BOOL,MPI_LOR,((PetscObject)ts)->comm);CHKERRQ(ierr); 3237324a0ffSLisandro Dalcin restart = outflag[0]; terminate = outflag[1]; 3247324a0ffSLisandro Dalcin if (restart) {ierr = TSRestartStep(ts);CHKERRQ(ierr);} 3257324a0ffSLisandro Dalcin if (terminate) {ierr = TSSetConvergedReason(ts,TS_CONVERGED_EVENT);CHKERRQ(ierr);} 3267324a0ffSLisandro Dalcin event->status = terminate ? TSEVENT_NONE : TSEVENT_RESET_NEXTSTEP; 327f7aea88cSShri Abhyankar 3284597913aSLisandro Dalcin /* Reset event residual functions as states might get changed by the postevent callback */ 329f443add6SLisandro Dalcin if (event->postevent) { 3308860a134SJunchao Zhang ierr = VecLockReadPush(U);CHKERRQ(ierr); 331f443add6SLisandro Dalcin ierr = (*event->eventhandler)(ts,t,U,event->fvalue,event->ctx);CHKERRQ(ierr); 3328860a134SJunchao Zhang ierr = VecLockReadPop(U);CHKERRQ(ierr); 333f443add6SLisandro Dalcin } 334f443add6SLisandro Dalcin 335f443add6SLisandro Dalcin /* Cache current time and event residual functions */ 336f443add6SLisandro Dalcin event->ptime_prev = t; 337f443add6SLisandro Dalcin for (i=0; i<event->nevents; i++) 338f443add6SLisandro Dalcin event->fvalue_prev[i] = event->fvalue[i]; 3394597913aSLisandro Dalcin 340d0578d90SShri Abhyankar /* Record the event in the event recorder */ 34180275a0aSLisandro Dalcin ierr = TSGetStepNumber(ts,&stepnum);CHKERRQ(ierr); 342f7aea88cSShri Abhyankar ctr = event->recorder.ctr; 343a4ffd976SShri Abhyankar if (ctr == event->recsize) { 344a4ffd976SShri Abhyankar ierr = TSEventRecorderResize(event);CHKERRQ(ierr); 345a4ffd976SShri Abhyankar } 346f7aea88cSShri Abhyankar event->recorder.time[ctr] = t; 347d0578d90SShri Abhyankar event->recorder.stepnum[ctr] = stepnum; 3484597913aSLisandro Dalcin event->recorder.nevents[ctr] = event->nevents_zero; 3494597913aSLisandro Dalcin for (i=0; i<event->nevents_zero; i++) event->recorder.eventidx[ctr][i] = event->events_zero[i]; 350f7aea88cSShri Abhyankar event->recorder.ctr++; 3512dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 3522dc7a7e3SShri Abhyankar } 3532dc7a7e3SShri Abhyankar 35402749585SLisandro Dalcin /* Uses Anderson-Bjorck variant of regula falsi method */ 355a3a8645aSShri Abhyankar PETSC_STATIC_INLINE PetscReal TSEventComputeStepSize(PetscReal tleft,PetscReal t,PetscReal tright,PetscScalar fleft,PetscScalar f,PetscScalar fright,PetscInt side,PetscReal dt) 35638bf2713SShri Abhyankar { 35702749585SLisandro Dalcin PetscReal new_dt, scal = 1.0; 358e2cdd850SShri Abhyankar if (PetscRealPart(fleft)*PetscRealPart(f) < 0) { 359e2cdd850SShri Abhyankar if (side == 1) { 360a6c783d2SShri Abhyankar scal = (PetscRealPart(fright) - PetscRealPart(f))/PetscRealPart(fright); 361a6c783d2SShri Abhyankar if (scal < PETSC_SMALL) scal = 0.5; 362e2cdd850SShri Abhyankar } 36302749585SLisandro Dalcin new_dt = (scal*PetscRealPart(fleft)*t - PetscRealPart(f)*tleft)/(scal*PetscRealPart(fleft) - PetscRealPart(f)) - tleft; 364e2cdd850SShri Abhyankar } else { 365e2cdd850SShri Abhyankar if (side == -1) { 366a6c783d2SShri Abhyankar scal = (PetscRealPart(fleft) - PetscRealPart(f))/PetscRealPart(fleft); 367a6c783d2SShri Abhyankar if (scal < PETSC_SMALL) scal = 0.5; 368e2cdd850SShri Abhyankar } 36902749585SLisandro Dalcin new_dt = (PetscRealPart(f)*tright - scal*PetscRealPart(fright)*t)/(PetscRealPart(f) - scal*PetscRealPart(fright)) - t; 370e2cdd850SShri Abhyankar } 37102749585SLisandro Dalcin return PetscMin(dt,new_dt); 37238bf2713SShri Abhyankar } 373e2cdd850SShri Abhyankar 37438bf2713SShri Abhyankar 3756427ac75SLisandro Dalcin PetscErrorCode TSEventHandler(TS ts) 3762dc7a7e3SShri Abhyankar { 3772dc7a7e3SShri Abhyankar PetscErrorCode ierr; 3786427ac75SLisandro Dalcin TSEvent event; 3792dc7a7e3SShri Abhyankar PetscReal t; 3802dc7a7e3SShri Abhyankar Vec U; 3812dc7a7e3SShri Abhyankar PetscInt i; 3827dbe0728SLisandro Dalcin PetscReal dt,dt_min; 3832dc7a7e3SShri Abhyankar PetscInt rollback=0,in[2],out[2]; 3849e12be75SShri Abhyankar PetscInt fvalue_sign,fvalueprev_sign; 3852dc7a7e3SShri Abhyankar 3862dc7a7e3SShri Abhyankar PetscFunctionBegin; 3876427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3886427ac75SLisandro Dalcin if (!ts->event) PetscFunctionReturn(0); 3896427ac75SLisandro Dalcin event = ts->event; 3902dc7a7e3SShri Abhyankar 3912dc7a7e3SShri Abhyankar ierr = TSGetTime(ts,&t);CHKERRQ(ierr); 3927dbe0728SLisandro Dalcin ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr); 3932dc7a7e3SShri Abhyankar ierr = TSGetSolution(ts,&U);CHKERRQ(ierr); 3942dc7a7e3SShri Abhyankar 3957dbe0728SLisandro Dalcin if (event->status == TSEVENT_NONE) { 3967dbe0728SLisandro Dalcin event->timestep_prev = dt; 3977dbe0728SLisandro Dalcin } 3987dbe0728SLisandro Dalcin 3992dc7a7e3SShri Abhyankar if (event->status == TSEVENT_RESET_NEXTSTEP) { 400458122a4SShri Abhyankar dt = event->timestep_posteventinterval; 401*e97c63d7SStefano Zampini if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 402*e97c63d7SStefano Zampini PetscReal maxdt = ts->max_time-t; 403*e97c63d7SStefano Zampini 404*e97c63d7SStefano Zampini dt = dt > maxdt ? maxdt : (PetscIsCloseAtTol(dt,maxdt,10*PETSC_MACHINE_EPSILON,0) ? maxdt : dt); 405*e97c63d7SStefano Zampini } 4067dbe0728SLisandro Dalcin ierr = TSSetTimeStep(ts,dt);CHKERRQ(ierr); 4072dc7a7e3SShri Abhyankar event->status = TSEVENT_NONE; 4082dc7a7e3SShri Abhyankar } 4092dc7a7e3SShri Abhyankar 4102dc7a7e3SShri Abhyankar if (event->status == TSEVENT_NONE) { 4117dbe0728SLisandro Dalcin event->ptime_end = t; 4122dc7a7e3SShri Abhyankar } 4132dc7a7e3SShri Abhyankar 4148860a134SJunchao Zhang ierr = VecLockReadPush(U);CHKERRQ(ierr); 4156427ac75SLisandro Dalcin ierr = (*event->eventhandler)(ts,t,U,event->fvalue,event->ctx);CHKERRQ(ierr); 4168860a134SJunchao Zhang ierr = VecLockReadPop(U);CHKERRQ(ierr); 4179e12be75SShri Abhyankar 4182dc7a7e3SShri Abhyankar for (i=0; i < event->nevents; i++) { 419e3005195SShri Abhyankar if (PetscAbsScalar(event->fvalue[i]) < event->vtol[i]) { 4202dc7a7e3SShri Abhyankar event->status = TSEVENT_ZERO; 421e2cdd850SShri Abhyankar event->fvalue_right[i] = event->fvalue[i]; 4229e12be75SShri Abhyankar continue; 423006e6a18SShri Abhyankar } 424d94325d3SShri Abhyankar fvalue_sign = PetscSign(PetscRealPart(event->fvalue[i])); 425d94325d3SShri Abhyankar fvalueprev_sign = PetscSign(PetscRealPart(event->fvalue_prev[i])); 426e3005195SShri Abhyankar if (fvalueprev_sign != 0 && (fvalue_sign != fvalueprev_sign) && (PetscAbsScalar(event->fvalue_prev[i]) > event->vtol[i])) { 427d94325d3SShri Abhyankar switch (event->direction[i]) { 428d94325d3SShri Abhyankar case -1: 429d94325d3SShri Abhyankar if (fvalue_sign < 0) { 4302dc7a7e3SShri Abhyankar rollback = 1; 431e2cdd850SShri Abhyankar 432e2cdd850SShri Abhyankar /* Compute new time step */ 433e2cdd850SShri Abhyankar dt = TSEventComputeStepSize(event->ptime_prev,t,event->ptime_right,event->fvalue_prev[i],event->fvalue[i],event->fvalue_right[i],event->side[i],dt); 434e2cdd850SShri Abhyankar 4356427ac75SLisandro Dalcin if (event->monitor) { 43638bf2713SShri Abhyankar 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); 437006e6a18SShri Abhyankar } 438e2cdd850SShri Abhyankar event->fvalue_right[i] = event->fvalue[i]; 439e2cdd850SShri Abhyankar event->side[i] = 1; 440e2cdd850SShri Abhyankar 441e2cdd850SShri Abhyankar if (!event->iterctr) event->zerocrossing[i] = PETSC_TRUE; 442e2cdd850SShri Abhyankar event->status = TSEVENT_LOCATED_INTERVAL; 4432dc7a7e3SShri Abhyankar } 444d94325d3SShri Abhyankar break; 445d94325d3SShri Abhyankar case 1: 446d94325d3SShri Abhyankar if (fvalue_sign > 0) { 447d94325d3SShri Abhyankar rollback = 1; 448e2cdd850SShri Abhyankar 449e2cdd850SShri Abhyankar /* Compute new time step */ 450e2cdd850SShri Abhyankar dt = TSEventComputeStepSize(event->ptime_prev,t,event->ptime_right,event->fvalue_prev[i],event->fvalue[i],event->fvalue_right[i],event->side[i],dt); 451e2cdd850SShri Abhyankar 4526427ac75SLisandro Dalcin if (event->monitor) { 45338bf2713SShri Abhyankar 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); 454006e6a18SShri Abhyankar } 455e2cdd850SShri Abhyankar event->fvalue_right[i] = event->fvalue[i]; 456e2cdd850SShri Abhyankar event->side[i] = 1; 457e2cdd850SShri Abhyankar 458e2cdd850SShri Abhyankar if (!event->iterctr) event->zerocrossing[i] = PETSC_TRUE; 459e2cdd850SShri Abhyankar event->status = TSEVENT_LOCATED_INTERVAL; 4602dc7a7e3SShri Abhyankar } 461d94325d3SShri Abhyankar break; 462d94325d3SShri Abhyankar case 0: 463d94325d3SShri Abhyankar rollback = 1; 464e2cdd850SShri Abhyankar 465e2cdd850SShri Abhyankar /* Compute new time step */ 466e2cdd850SShri Abhyankar dt = TSEventComputeStepSize(event->ptime_prev,t,event->ptime_right,event->fvalue_prev[i],event->fvalue[i],event->fvalue_right[i],event->side[i],dt); 467e2cdd850SShri Abhyankar 4686427ac75SLisandro Dalcin if (event->monitor) { 46938bf2713SShri Abhyankar 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); 470006e6a18SShri Abhyankar } 471e2cdd850SShri Abhyankar event->fvalue_right[i] = event->fvalue[i]; 472e2cdd850SShri Abhyankar event->side[i] = 1; 473e2cdd850SShri Abhyankar 474e2cdd850SShri Abhyankar if (!event->iterctr) event->zerocrossing[i] = PETSC_TRUE; 475e2cdd850SShri Abhyankar event->status = TSEVENT_LOCATED_INTERVAL; 476e2cdd850SShri Abhyankar 477d94325d3SShri Abhyankar break; 478d94325d3SShri Abhyankar } 479d94325d3SShri Abhyankar } 480d94325d3SShri Abhyankar } 4817dbe0728SLisandro Dalcin 4822589fa24SLisandro Dalcin in[0] = event->status; in[1] = rollback; 4837dbe0728SLisandro Dalcin ierr = MPIU_Allreduce(in,out,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr); 4842589fa24SLisandro Dalcin event->status = (TSEventStatus)out[0]; rollback = out[1]; 4852589fa24SLisandro Dalcin if (rollback) event->status = TSEVENT_LOCATED_INTERVAL; 4862dc7a7e3SShri Abhyankar 4877dbe0728SLisandro Dalcin event->nevents_zero = 0; 4889e12be75SShri Abhyankar if (event->status == TSEVENT_ZERO) { 4899e12be75SShri Abhyankar for (i=0; i < event->nevents; i++) { 4909e12be75SShri Abhyankar if (PetscAbsScalar(event->fvalue[i]) < event->vtol[i]) { 4919e12be75SShri Abhyankar event->events_zero[event->nevents_zero++] = i; 4926427ac75SLisandro Dalcin if (event->monitor) { 49338bf2713SShri Abhyankar ierr = PetscViewerASCIIPrintf(event->monitor,"TSEvent: Event %D zero crossing at time %g located in %D iterations\n",i,(double)t,event->iterctr);CHKERRQ(ierr); 4949e12be75SShri Abhyankar } 495e2cdd850SShri Abhyankar event->zerocrossing[i] = PETSC_FALSE; 4969e12be75SShri Abhyankar } 497e2cdd850SShri Abhyankar event->side[i] = 0; 4989e12be75SShri Abhyankar } 4994597913aSLisandro Dalcin ierr = TSPostEvent(ts,t,U);CHKERRQ(ierr); 5009e12be75SShri Abhyankar 501e2cdd850SShri Abhyankar dt = event->ptime_end - t; 502ad508104SStefano Zampini if (PetscAbsReal(dt) < PETSC_SMALL) { /* we hit the event, continue with the candidate time step */ 503ad508104SStefano Zampini dt = event->timestep_prev; 504ad508104SStefano Zampini event->status = TSEVENT_NONE; 505ad508104SStefano Zampini } 506*e97c63d7SStefano Zampini if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 507*e97c63d7SStefano Zampini PetscReal maxdt = ts->max_time-t; 508*e97c63d7SStefano Zampini 509*e97c63d7SStefano Zampini dt = dt > maxdt ? maxdt : (PetscIsCloseAtTol(dt,maxdt,10*PETSC_MACHINE_EPSILON,0) ? maxdt : dt); 510*e97c63d7SStefano Zampini } 5119e12be75SShri Abhyankar ierr = TSSetTimeStep(ts,dt);CHKERRQ(ierr); 51238bf2713SShri Abhyankar event->iterctr = 0; 5139e12be75SShri Abhyankar PetscFunctionReturn(0); 5149e12be75SShri Abhyankar } 5159e12be75SShri Abhyankar 5162dc7a7e3SShri Abhyankar if (event->status == TSEVENT_LOCATED_INTERVAL) { 5172dc7a7e3SShri Abhyankar ierr = TSRollBack(ts);CHKERRQ(ierr); 5182589fa24SLisandro Dalcin ierr = TSSetConvergedReason(ts,TS_CONVERGED_ITERATING);CHKERRQ(ierr); 5192dc7a7e3SShri Abhyankar event->status = TSEVENT_PROCESSING; 520e2cdd850SShri Abhyankar event->ptime_right = t; 5212dc7a7e3SShri Abhyankar } else { 5222dc7a7e3SShri Abhyankar for (i=0; i < event->nevents; i++) { 523e2cdd850SShri Abhyankar if (event->status == TSEVENT_PROCESSING && event->zerocrossing[i]) { 524e2cdd850SShri Abhyankar /* Compute new time step */ 525e2cdd850SShri Abhyankar dt = TSEventComputeStepSize(event->ptime_prev,t,event->ptime_right,event->fvalue_prev[i],event->fvalue[i],event->fvalue_right[i],event->side[i],dt); 526e2cdd850SShri Abhyankar event->side[i] = -1; 527e2cdd850SShri Abhyankar } 5282dc7a7e3SShri Abhyankar event->fvalue_prev[i] = event->fvalue[i]; 5292dc7a7e3SShri Abhyankar } 530e2cdd850SShri Abhyankar if (event->monitor && event->status == TSEVENT_PROCESSING) { 53138bf2713SShri Abhyankar 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); 5322dc7a7e3SShri Abhyankar } 53338bf2713SShri Abhyankar event->ptime_prev = t; 53438bf2713SShri Abhyankar } 53538bf2713SShri Abhyankar 53638bf2713SShri Abhyankar if (event->status == TSEVENT_PROCESSING) event->iterctr++; 5379e12be75SShri Abhyankar 5387dbe0728SLisandro Dalcin ierr = MPIU_Allreduce(&dt,&dt_min,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr); 5397dbe0728SLisandro Dalcin ierr = TSSetTimeStep(ts,dt_min);CHKERRQ(ierr); 5402dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 5412dc7a7e3SShri Abhyankar } 5422dc7a7e3SShri Abhyankar 5436427ac75SLisandro Dalcin PetscErrorCode TSAdjointEventHandler(TS ts) 544d0578d90SShri Abhyankar { 545d0578d90SShri Abhyankar PetscErrorCode ierr; 5466427ac75SLisandro Dalcin TSEvent event; 547d0578d90SShri Abhyankar PetscReal t; 548d0578d90SShri Abhyankar Vec U; 549d0578d90SShri Abhyankar PetscInt ctr; 550d0578d90SShri Abhyankar PetscBool forwardsolve=PETSC_FALSE; /* Flag indicating that TS is doing an adjoint solve */ 551d0578d90SShri Abhyankar 552d0578d90SShri Abhyankar PetscFunctionBegin; 5536427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 5546427ac75SLisandro Dalcin if (!ts->event) PetscFunctionReturn(0); 5556427ac75SLisandro Dalcin event = ts->event; 556d0578d90SShri Abhyankar 557d0578d90SShri Abhyankar ierr = TSGetTime(ts,&t);CHKERRQ(ierr); 558d0578d90SShri Abhyankar ierr = TSGetSolution(ts,&U);CHKERRQ(ierr); 559d0578d90SShri Abhyankar 560d0578d90SShri Abhyankar ctr = event->recorder.ctr-1; 561bcbf8bb3SShri Abhyankar if (ctr >= 0 && PetscAbsReal(t - event->recorder.time[ctr]) < PETSC_SMALL) { 562d0578d90SShri Abhyankar /* Call the user postevent function */ 563d0578d90SShri Abhyankar if (event->postevent) { 5646427ac75SLisandro Dalcin ierr = (*event->postevent)(ts,event->recorder.nevents[ctr],event->recorder.eventidx[ctr],t,U,forwardsolve,event->ctx);CHKERRQ(ierr); 565d0578d90SShri Abhyankar event->recorder.ctr--; 566d0578d90SShri Abhyankar } 567d0578d90SShri Abhyankar } 568d0578d90SShri Abhyankar 569d0578d90SShri Abhyankar PetscBarrier((PetscObject)ts); 570d0578d90SShri Abhyankar PetscFunctionReturn(0); 571d0578d90SShri Abhyankar } 572