1af0996ceSBarry Smith #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 22dc7a7e3SShri Abhyankar 32dc7a7e3SShri Abhyankar #undef __FUNCT__ 46427ac75SLisandro Dalcin #define __FUNCT__ "TSEventInitialize" 56fea3669SShri Abhyankar /* 66427ac75SLisandro Dalcin TSEventInitialize - Initializes TSEvent for TSSolve 76fea3669SShri Abhyankar */ 86427ac75SLisandro Dalcin PetscErrorCode TSEventInitialize(TSEvent event,TS ts,PetscReal t,Vec U) 96fea3669SShri Abhyankar { 106fea3669SShri Abhyankar PetscErrorCode ierr; 116fea3669SShri Abhyankar 126fea3669SShri Abhyankar PetscFunctionBegin; 136427ac75SLisandro Dalcin if (!event) PetscFunctionReturn(0); 146427ac75SLisandro Dalcin PetscValidPointer(event,1); 156427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,2); 166427ac75SLisandro Dalcin PetscValidHeaderSpecific(U,VEC_CLASSID,4); 176fea3669SShri Abhyankar event->ptime_prev = t; 1838bf2713SShri Abhyankar event->iterctr = 0; 196427ac75SLisandro Dalcin ierr = (*event->eventhandler)(ts,t,U,event->fvalue_prev,event->ctx);CHKERRQ(ierr); 206fea3669SShri Abhyankar /* Initialize the event recorder */ 216fea3669SShri Abhyankar event->recorder.ctr = 0; 226fea3669SShri Abhyankar PetscFunctionReturn(0); 236fea3669SShri Abhyankar } 246fea3669SShri Abhyankar 256fea3669SShri Abhyankar #undef __FUNCT__ 267dbe0728SLisandro Dalcin #define __FUNCT__ "TSEventDestroy" 277dbe0728SLisandro Dalcin PetscErrorCode TSEventDestroy(TSEvent *event) 287dbe0728SLisandro Dalcin { 297dbe0728SLisandro Dalcin PetscErrorCode ierr; 307dbe0728SLisandro Dalcin PetscInt i; 317dbe0728SLisandro Dalcin 327dbe0728SLisandro Dalcin PetscFunctionBegin; 337dbe0728SLisandro Dalcin PetscValidPointer(event,1); 347dbe0728SLisandro Dalcin if (!*event) PetscFunctionReturn(0); 357dbe0728SLisandro Dalcin ierr = PetscFree((*event)->fvalue);CHKERRQ(ierr); 367dbe0728SLisandro Dalcin ierr = PetscFree((*event)->fvalue_prev);CHKERRQ(ierr); 37e2cdd850SShri Abhyankar ierr = PetscFree((*event)->fvalue_right);CHKERRQ(ierr); 38e2cdd850SShri Abhyankar ierr = PetscFree((*event)->zerocrossing);CHKERRQ(ierr); 39e2cdd850SShri Abhyankar ierr = PetscFree((*event)->side);CHKERRQ(ierr); 407dbe0728SLisandro Dalcin ierr = PetscFree((*event)->direction);CHKERRQ(ierr); 417dbe0728SLisandro Dalcin ierr = PetscFree((*event)->terminate);CHKERRQ(ierr); 427dbe0728SLisandro Dalcin ierr = PetscFree((*event)->events_zero);CHKERRQ(ierr); 437dbe0728SLisandro Dalcin ierr = PetscFree((*event)->vtol);CHKERRQ(ierr); 44a4ffd976SShri Abhyankar 45a4ffd976SShri Abhyankar for (i=0; i < (*event)->recsize; i++) { 467dbe0728SLisandro Dalcin ierr = PetscFree((*event)->recorder.eventidx[i]);CHKERRQ(ierr); 477dbe0728SLisandro Dalcin } 48a4ffd976SShri Abhyankar ierr = PetscFree((*event)->recorder.eventidx);CHKERRQ(ierr); 49a4ffd976SShri Abhyankar ierr = PetscFree((*event)->recorder.nevents);CHKERRQ(ierr); 50a4ffd976SShri Abhyankar ierr = PetscFree((*event)->recorder.stepnum);CHKERRQ(ierr); 51a4ffd976SShri Abhyankar ierr = PetscFree((*event)->recorder.time);CHKERRQ(ierr); 52a4ffd976SShri Abhyankar 537dbe0728SLisandro Dalcin ierr = PetscViewerDestroy(&(*event)->monitor);CHKERRQ(ierr); 547dbe0728SLisandro Dalcin ierr = PetscFree(*event);CHKERRQ(ierr); 557dbe0728SLisandro Dalcin PetscFunctionReturn(0); 567dbe0728SLisandro Dalcin } 577dbe0728SLisandro Dalcin 587dbe0728SLisandro Dalcin #undef __FUNCT__ 59e3005195SShri Abhyankar #define __FUNCT__ "TSSetEventTolerances" 60e3005195SShri Abhyankar /*@ 61e3005195SShri Abhyankar TSSetEventTolerances - Set tolerances for event zero crossings when using event handler 62e3005195SShri Abhyankar 63e3005195SShri Abhyankar Logically Collective 64e3005195SShri Abhyankar 65e3005195SShri Abhyankar Input Arguments: 66e3005195SShri Abhyankar + ts - time integration context 67e3005195SShri Abhyankar . tol - scalar tolerance, PETSC_DECIDE to leave current value 68e3005195SShri Abhyankar - vtol - array of tolerances or NULL, used in preference to tol if present 69e3005195SShri Abhyankar 702589fa24SLisandro Dalcin Options Database Keys: 712589fa24SLisandro Dalcin . -ts_event_tol <tol> tolerance for event zero crossing 72e3005195SShri Abhyankar 73e3005195SShri Abhyankar Notes: 74f25fe674SLisandro Dalcin Must call TSSetEventHandler() before setting the tolerances. 75e3005195SShri Abhyankar 76e3005195SShri Abhyankar The size of vtol is equal to the number of events. 77e3005195SShri Abhyankar 78e3005195SShri Abhyankar Level: beginner 79e3005195SShri Abhyankar 80f25fe674SLisandro Dalcin .seealso: TS, TSEvent, TSSetEventHandler() 81e3005195SShri Abhyankar @*/ 826427ac75SLisandro Dalcin PetscErrorCode TSSetEventTolerances(TS ts,PetscReal tol,PetscReal vtol[]) 83e3005195SShri Abhyankar { 846427ac75SLisandro Dalcin TSEvent event; 85e3005195SShri Abhyankar PetscInt i; 86e3005195SShri Abhyankar 87e3005195SShri Abhyankar PetscFunctionBegin; 886427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 896427ac75SLisandro Dalcin if (vtol) PetscValidRealPointer(vtol,3); 90f25fe674SLisandro Dalcin if (!ts->event) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must set the events first by calling TSSetEventHandler()"); 916427ac75SLisandro Dalcin 926427ac75SLisandro Dalcin event = ts->event; 93e3005195SShri Abhyankar if (vtol) { 94e3005195SShri Abhyankar for (i=0; i < event->nevents; i++) event->vtol[i] = vtol[i]; 95e3005195SShri Abhyankar } else { 96e3005195SShri Abhyankar if (tol != PETSC_DECIDE || tol != PETSC_DEFAULT) { 97e3005195SShri Abhyankar for (i=0; i < event->nevents; i++) event->vtol[i] = tol; 98e3005195SShri Abhyankar } 99e3005195SShri Abhyankar } 100e3005195SShri Abhyankar PetscFunctionReturn(0); 101e3005195SShri Abhyankar } 102e3005195SShri Abhyankar 103e3005195SShri Abhyankar #undef __FUNCT__ 104f25fe674SLisandro Dalcin #define __FUNCT__ "TSSetEventHandler" 1052dc7a7e3SShri Abhyankar /*@C 106f25fe674SLisandro Dalcin TSSetEventHandler - Sets a monitoring function used for detecting events 1072dc7a7e3SShri Abhyankar 1082dc7a7e3SShri Abhyankar Logically Collective on TS 1092dc7a7e3SShri Abhyankar 1102dc7a7e3SShri Abhyankar Input Parameters: 1112dc7a7e3SShri Abhyankar + ts - the TS context obtained from TSCreate() 1122dc7a7e3SShri Abhyankar . nevents - number of local events 113d94325d3SShri Abhyankar . direction - direction of zero crossing to be detected. -1 => Zero crossing in negative direction, 114d94325d3SShri Abhyankar +1 => Zero crossing in positive direction, 0 => both ways (one for each event) 115d94325d3SShri Abhyankar . terminate - flag to indicate whether time stepping should be terminated after 116d94325d3SShri Abhyankar event is detected (one for each event) 1176427ac75SLisandro Dalcin . eventhandler - event monitoring routine 1182dc7a7e3SShri Abhyankar . postevent - [optional] post-event function 1192589fa24SLisandro Dalcin - ctx - [optional] user-defined context for private data for the 1202dc7a7e3SShri Abhyankar event monitor and post event routine (use NULL if no 1212dc7a7e3SShri Abhyankar context is desired) 1222dc7a7e3SShri Abhyankar 1236427ac75SLisandro Dalcin Calling sequence of eventhandler: 124*3a88037aSBarry Smith PetscErrorCode PetscEventHandler(TS ts,PetscReal t,Vec U,PetscScalar fvalue[],void* ctx) 1252dc7a7e3SShri Abhyankar 1262dc7a7e3SShri Abhyankar Input Parameters: 1272dc7a7e3SShri Abhyankar + ts - the TS context 1282dc7a7e3SShri Abhyankar . t - current time 1292dc7a7e3SShri Abhyankar . U - current iterate 1306427ac75SLisandro Dalcin - ctx - [optional] context passed with eventhandler 1312dc7a7e3SShri Abhyankar 1322dc7a7e3SShri Abhyankar Output parameters: 133d94325d3SShri Abhyankar . fvalue - function value of events at time t 1342dc7a7e3SShri Abhyankar 1352dc7a7e3SShri Abhyankar Calling sequence of postevent: 1362589fa24SLisandro Dalcin PetscErrorCode PostEvent(TS ts,PetscInt nevents_zero,PetscInt events_zero[],PetscReal t,Vec U,PetscBool forwardsolve,void* ctx) 1372dc7a7e3SShri Abhyankar 1382dc7a7e3SShri Abhyankar Input Parameters: 1392dc7a7e3SShri Abhyankar + ts - the TS context 1402dc7a7e3SShri Abhyankar . nevents_zero - number of local events whose event function is zero 1412dc7a7e3SShri Abhyankar . events_zero - indices of local events which have reached zero 1422dc7a7e3SShri Abhyankar . t - current time 1432dc7a7e3SShri Abhyankar . U - current solution 144031fbad4SShri Abhyankar . forwardsolve - Flag to indicate whether TS is doing a forward solve (1) or adjoint solve (0) 1456427ac75SLisandro Dalcin - ctx - the context passed with eventhandler 1462dc7a7e3SShri Abhyankar 1472dc7a7e3SShri Abhyankar Level: intermediate 1482dc7a7e3SShri Abhyankar 14902749585SLisandro Dalcin .keywords: TS, event, set 1502dc7a7e3SShri Abhyankar 1512dc7a7e3SShri Abhyankar .seealso: TSCreate(), TSSetTimeStep(), TSSetConvergedReason() 1522dc7a7e3SShri Abhyankar @*/ 1532589fa24SLisandro 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) 1542dc7a7e3SShri Abhyankar { 1552dc7a7e3SShri Abhyankar PetscErrorCode ierr; 1562dc7a7e3SShri Abhyankar TSEvent event; 157d94325d3SShri Abhyankar PetscInt i; 158006e6a18SShri Abhyankar PetscBool flg; 159a6c783d2SShri Abhyankar #if defined PETSC_USE_REAL_SINGLE 160a6c783d2SShri Abhyankar PetscReal tol=1e-4; 161a6c783d2SShri Abhyankar #else 162d569cc17SSatish Balay PetscReal tol=1e-6; 163a6c783d2SShri Abhyankar #endif 1642dc7a7e3SShri Abhyankar 1652dc7a7e3SShri Abhyankar PetscFunctionBegin; 1666427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1676427ac75SLisandro Dalcin PetscValidIntPointer(direction,2); 1686427ac75SLisandro Dalcin PetscValidIntPointer(terminate,3); 1696427ac75SLisandro Dalcin 1706427ac75SLisandro Dalcin ierr = PetscNewLog(ts,&event);CHKERRQ(ierr); 171854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->fvalue);CHKERRQ(ierr); 172854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->fvalue_prev);CHKERRQ(ierr); 173e2cdd850SShri Abhyankar ierr = PetscMalloc1(nevents,&event->fvalue_right);CHKERRQ(ierr); 174e2cdd850SShri Abhyankar ierr = PetscMalloc1(nevents,&event->zerocrossing);CHKERRQ(ierr); 175e2cdd850SShri Abhyankar ierr = PetscMalloc1(nevents,&event->side);CHKERRQ(ierr); 176854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->direction);CHKERRQ(ierr); 177854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->terminate);CHKERRQ(ierr); 178e3005195SShri Abhyankar ierr = PetscMalloc1(nevents,&event->vtol);CHKERRQ(ierr); 179d94325d3SShri Abhyankar for (i=0; i < nevents; i++) { 180d94325d3SShri Abhyankar event->direction[i] = direction[i]; 181d94325d3SShri Abhyankar event->terminate[i] = terminate[i]; 182e2cdd850SShri Abhyankar event->zerocrossing[i] = PETSC_FALSE; 183e2cdd850SShri Abhyankar event->side[i] = 0; 184d94325d3SShri Abhyankar } 185854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->events_zero);CHKERRQ(ierr); 1862589fa24SLisandro Dalcin event->nevents = nevents; 1876427ac75SLisandro Dalcin event->eventhandler = eventhandler; 1882dc7a7e3SShri Abhyankar event->postevent = postevent; 1896427ac75SLisandro Dalcin event->ctx = ctx; 1902dc7a7e3SShri Abhyankar 19102749585SLisandro Dalcin event->recsize = 8; /* Initial size of the recorder */ 192a9514d71SShri Abhyankar ierr = PetscOptionsBegin(((PetscObject)ts)->comm,"","TS Event options","");CHKERRQ(ierr); 1932dc7a7e3SShri Abhyankar { 19402749585SLisandro Dalcin ierr = PetscOptionsReal("-ts_event_tol","Scalar event tolerance for zero crossing check","TSSetEventTolerances",tol,&tol,NULL);CHKERRQ(ierr); 195006e6a18SShri Abhyankar ierr = PetscOptionsName("-ts_event_monitor","Print choices made by event handler","",&flg);CHKERRQ(ierr); 196a4ffd976SShri Abhyankar ierr = PetscOptionsInt("-ts_event_recorder_initial_size","Initial size of event recorder","",event->recsize,&event->recsize,NULL);CHKERRQ(ierr); 1972dc7a7e3SShri Abhyankar } 1989e12be75SShri Abhyankar PetscOptionsEnd(); 199a4ffd976SShri Abhyankar 200a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.time);CHKERRQ(ierr); 201a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.stepnum);CHKERRQ(ierr); 202a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.nevents);CHKERRQ(ierr); 203a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.eventidx);CHKERRQ(ierr); 204a4ffd976SShri Abhyankar for (i=0; i < event->recsize; i++) { 205a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->nevents,&event->recorder.eventidx[i]);CHKERRQ(ierr); 206a4ffd976SShri Abhyankar } 207a4ffd976SShri Abhyankar 208e3005195SShri Abhyankar for (i=0; i < event->nevents; i++) event->vtol[i] = tol; 2096427ac75SLisandro Dalcin if (flg) {ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,"stdout",&event->monitor);CHKERRQ(ierr);} 2109e12be75SShri Abhyankar 2116427ac75SLisandro Dalcin ierr = TSEventDestroy(&ts->event);CHKERRQ(ierr); 212d94325d3SShri Abhyankar ts->event = event; 2132dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 2142dc7a7e3SShri Abhyankar } 2152dc7a7e3SShri Abhyankar 216a4ffd976SShri Abhyankar #undef __FUNCT__ 217a4ffd976SShri Abhyankar #define __FUNCT__ "TSEventRecorderResize" 218a4ffd976SShri Abhyankar /* 219a4ffd976SShri Abhyankar TSEventRecorderResize - Resizes (2X) the event recorder arrays whenever the recording limit (event->recsize) 220a4ffd976SShri Abhyankar is reached. 221a4ffd976SShri Abhyankar */ 22202749585SLisandro Dalcin static PetscErrorCode TSEventRecorderResize(TSEvent event) 223a4ffd976SShri Abhyankar { 224a4ffd976SShri Abhyankar PetscErrorCode ierr; 225a4ffd976SShri Abhyankar PetscReal *time; 226a4ffd976SShri Abhyankar PetscInt *stepnum; 227a4ffd976SShri Abhyankar PetscInt *nevents; 228a4ffd976SShri Abhyankar PetscInt **eventidx; 229a4ffd976SShri Abhyankar PetscInt i,fact=2; 230a4ffd976SShri Abhyankar 231a4ffd976SShri Abhyankar PetscFunctionBegin; 232a4ffd976SShri Abhyankar 233a4ffd976SShri Abhyankar /* Create large arrays */ 234a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&time);CHKERRQ(ierr); 235a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&stepnum);CHKERRQ(ierr); 236a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&nevents);CHKERRQ(ierr); 237a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&eventidx);CHKERRQ(ierr); 238a4ffd976SShri Abhyankar for (i=0; i < fact*event->recsize; i++) { 239a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->nevents,&eventidx[i]);CHKERRQ(ierr); 240a4ffd976SShri Abhyankar } 241a4ffd976SShri Abhyankar 242a4ffd976SShri Abhyankar /* Copy over data */ 243a4ffd976SShri Abhyankar ierr = PetscMemcpy(time,event->recorder.time,event->recsize*sizeof(PetscReal));CHKERRQ(ierr); 244a4ffd976SShri Abhyankar ierr = PetscMemcpy(stepnum,event->recorder.stepnum,event->recsize*sizeof(PetscInt));CHKERRQ(ierr); 245a4ffd976SShri Abhyankar ierr = PetscMemcpy(nevents,event->recorder.nevents,event->recsize*sizeof(PetscInt));CHKERRQ(ierr); 246a4ffd976SShri Abhyankar for (i=0; i < event->recsize; i++) { 247a4ffd976SShri Abhyankar ierr = PetscMemcpy(eventidx[i],event->recorder.eventidx[i],event->recorder.nevents[i]*sizeof(PetscInt));CHKERRQ(ierr); 248a4ffd976SShri Abhyankar } 249a4ffd976SShri Abhyankar 250a4ffd976SShri Abhyankar /* Destroy old arrays */ 251a4ffd976SShri Abhyankar for (i=0; i < event->recsize; i++) { 252a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.eventidx[i]);CHKERRQ(ierr); 253a4ffd976SShri Abhyankar } 254a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.eventidx);CHKERRQ(ierr); 255a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.nevents);CHKERRQ(ierr); 256a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.stepnum);CHKERRQ(ierr); 257a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.time);CHKERRQ(ierr); 258a4ffd976SShri Abhyankar 259a4ffd976SShri Abhyankar /* Set pointers */ 260a4ffd976SShri Abhyankar event->recorder.time = time; 261a4ffd976SShri Abhyankar event->recorder.stepnum = stepnum; 262a4ffd976SShri Abhyankar event->recorder.nevents = nevents; 263a4ffd976SShri Abhyankar event->recorder.eventidx = eventidx; 264a4ffd976SShri Abhyankar 265a4ffd976SShri Abhyankar /* Double size */ 266a4ffd976SShri Abhyankar event->recsize *= fact; 267a4ffd976SShri Abhyankar 268a4ffd976SShri Abhyankar PetscFunctionReturn(0); 269a4ffd976SShri Abhyankar } 270a4ffd976SShri Abhyankar 271031fbad4SShri Abhyankar /* 2724597913aSLisandro Dalcin Helper rutine to handle user postenvents and recording 273031fbad4SShri Abhyankar */ 274031fbad4SShri Abhyankar #undef __FUNCT__ 275031fbad4SShri Abhyankar #define __FUNCT__ "TSPostEvent" 2764597913aSLisandro Dalcin static PetscErrorCode TSPostEvent(TS ts,PetscReal t,Vec U) 2772dc7a7e3SShri Abhyankar { 2782dc7a7e3SShri Abhyankar PetscErrorCode ierr; 2792dc7a7e3SShri Abhyankar TSEvent event = ts->event; 2802dc7a7e3SShri Abhyankar PetscBool terminate = PETSC_FALSE; 28128d5b5d6SLisandro Dalcin PetscBool restart = PETSC_FALSE; 282d0578d90SShri Abhyankar PetscInt i,ctr,stepnum; 28328d5b5d6SLisandro Dalcin PetscBool ts_terminate,ts_restart; 2844597913aSLisandro Dalcin PetscBool forwardsolve = PETSC_TRUE; /* Flag indicating that TS is doing a forward solve */ 2852dc7a7e3SShri Abhyankar 2862dc7a7e3SShri Abhyankar PetscFunctionBegin; 2872dc7a7e3SShri Abhyankar if (event->postevent) { 28828d5b5d6SLisandro Dalcin PetscObjectState state_prev,state_post; 28928d5b5d6SLisandro Dalcin ierr = PetscObjectStateGet((PetscObject)U,&state_prev);CHKERRQ(ierr); 2904597913aSLisandro Dalcin ierr = (*event->postevent)(ts,event->nevents_zero,event->events_zero,t,U,forwardsolve,event->ctx);CHKERRQ(ierr); 29128d5b5d6SLisandro Dalcin ierr = PetscObjectStateGet((PetscObject)U,&state_post);CHKERRQ(ierr); 29228d5b5d6SLisandro Dalcin if (state_prev != state_post) restart = PETSC_TRUE; 2932dc7a7e3SShri Abhyankar } 2944597913aSLisandro Dalcin 29528d5b5d6SLisandro Dalcin /* Handle termination events and step restart */ 29628d5b5d6SLisandro Dalcin for (i=0; i<event->nevents_zero; i++) if (event->terminate[event->events_zero[i]]) terminate = PETSC_TRUE; 297b2566f29SBarry Smith ierr = MPIU_Allreduce(&terminate,&ts_terminate,1,MPIU_BOOL,MPI_LOR,((PetscObject)ts)->comm);CHKERRQ(ierr); 29828d5b5d6SLisandro Dalcin if (ts_terminate) {ierr = TSSetConvergedReason(ts,TS_CONVERGED_EVENT);CHKERRQ(ierr);} 29928d5b5d6SLisandro Dalcin event->status = ts_terminate ? TSEVENT_NONE : TSEVENT_RESET_NEXTSTEP; 30028d5b5d6SLisandro Dalcin ierr = MPIU_Allreduce(&restart,&ts_restart,1,MPIU_BOOL,MPI_LOR,((PetscObject)ts)->comm);CHKERRQ(ierr); 30128d5b5d6SLisandro Dalcin if (ts_restart) ts->steprestart = PETSC_TRUE; 302f7aea88cSShri Abhyankar 3034597913aSLisandro Dalcin event->ptime_prev = t; 3044597913aSLisandro Dalcin /* Reset event residual functions as states might get changed by the postevent callback */ 3054597913aSLisandro Dalcin if (event->postevent) {ierr = (*event->eventhandler)(ts,t,U,event->fvalue,event->ctx);CHKERRQ(ierr);} 3064597913aSLisandro Dalcin /* Cache current event residual functions */ 3074597913aSLisandro Dalcin for (i=0; i < event->nevents; i++) event->fvalue_prev[i] = event->fvalue[i]; 3084597913aSLisandro Dalcin 309d0578d90SShri Abhyankar /* Record the event in the event recorder */ 310d0578d90SShri Abhyankar ierr = TSGetTimeStepNumber(ts,&stepnum);CHKERRQ(ierr); 311f7aea88cSShri Abhyankar ctr = event->recorder.ctr; 312a4ffd976SShri Abhyankar if (ctr == event->recsize) { 313a4ffd976SShri Abhyankar ierr = TSEventRecorderResize(event);CHKERRQ(ierr); 314a4ffd976SShri Abhyankar } 315f7aea88cSShri Abhyankar event->recorder.time[ctr] = t; 316d0578d90SShri Abhyankar event->recorder.stepnum[ctr] = stepnum; 3174597913aSLisandro Dalcin event->recorder.nevents[ctr] = event->nevents_zero; 3184597913aSLisandro Dalcin for (i=0; i<event->nevents_zero; i++) event->recorder.eventidx[ctr][i] = event->events_zero[i]; 319f7aea88cSShri Abhyankar event->recorder.ctr++; 3202dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 3212dc7a7e3SShri Abhyankar } 3222dc7a7e3SShri Abhyankar 32302749585SLisandro Dalcin /* Uses Anderson-Bjorck variant of regula falsi method */ 324a3a8645aSShri Abhyankar PETSC_STATIC_INLINE PetscReal TSEventComputeStepSize(PetscReal tleft,PetscReal t,PetscReal tright,PetscScalar fleft,PetscScalar f,PetscScalar fright,PetscInt side,PetscReal dt) 32538bf2713SShri Abhyankar { 32602749585SLisandro Dalcin PetscReal new_dt, scal = 1.0; 327e2cdd850SShri Abhyankar if (PetscRealPart(fleft)*PetscRealPart(f) < 0) { 328e2cdd850SShri Abhyankar if (side == 1) { 329a6c783d2SShri Abhyankar scal = (PetscRealPart(fright) - PetscRealPart(f))/PetscRealPart(fright); 330a6c783d2SShri Abhyankar if (scal < PETSC_SMALL) scal = 0.5; 331e2cdd850SShri Abhyankar } 33202749585SLisandro Dalcin new_dt = (scal*PetscRealPart(fleft)*t - PetscRealPart(f)*tleft)/(scal*PetscRealPart(fleft) - PetscRealPart(f)) - tleft; 333e2cdd850SShri Abhyankar } else { 334e2cdd850SShri Abhyankar if (side == -1) { 335a6c783d2SShri Abhyankar scal = (PetscRealPart(fleft) - PetscRealPart(f))/PetscRealPart(fleft); 336a6c783d2SShri Abhyankar if (scal < PETSC_SMALL) scal = 0.5; 337e2cdd850SShri Abhyankar } 33802749585SLisandro Dalcin new_dt = (PetscRealPart(f)*tright - scal*PetscRealPart(fright)*t)/(PetscRealPart(f) - scal*PetscRealPart(fright)) - t; 339e2cdd850SShri Abhyankar } 34002749585SLisandro Dalcin return PetscMin(dt,new_dt); 34138bf2713SShri Abhyankar } 342e2cdd850SShri Abhyankar 34338bf2713SShri Abhyankar 3442dc7a7e3SShri Abhyankar #undef __FUNCT__ 3456427ac75SLisandro Dalcin #define __FUNCT__ "TSEventHandler" 3466427ac75SLisandro Dalcin PetscErrorCode TSEventHandler(TS ts) 3472dc7a7e3SShri Abhyankar { 3482dc7a7e3SShri Abhyankar PetscErrorCode ierr; 3496427ac75SLisandro Dalcin TSEvent event; 3502dc7a7e3SShri Abhyankar PetscReal t; 3512dc7a7e3SShri Abhyankar Vec U; 3522dc7a7e3SShri Abhyankar PetscInt i; 3537dbe0728SLisandro Dalcin PetscReal dt,dt_min; 3542dc7a7e3SShri Abhyankar PetscInt rollback=0,in[2],out[2]; 3559e12be75SShri Abhyankar PetscInt fvalue_sign,fvalueprev_sign; 3562dc7a7e3SShri Abhyankar 3572dc7a7e3SShri Abhyankar PetscFunctionBegin; 3586427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3596427ac75SLisandro Dalcin if (!ts->event) PetscFunctionReturn(0); 3606427ac75SLisandro Dalcin event = ts->event; 3612dc7a7e3SShri Abhyankar 3622dc7a7e3SShri Abhyankar ierr = TSGetTime(ts,&t);CHKERRQ(ierr); 3637dbe0728SLisandro Dalcin ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr); 3642dc7a7e3SShri Abhyankar ierr = TSGetSolution(ts,&U);CHKERRQ(ierr); 3652dc7a7e3SShri Abhyankar 3667dbe0728SLisandro Dalcin if (event->status == TSEVENT_NONE) { 3672d5bd56dSLisandro Dalcin if (ts->steps == 1) /* After first successful step */ 3682d5bd56dSLisandro Dalcin event->timestep_orig = ts->ptime - ts->ptime_prev; 3697dbe0728SLisandro Dalcin event->timestep_prev = dt; 3707dbe0728SLisandro Dalcin } 3717dbe0728SLisandro Dalcin 3722dc7a7e3SShri Abhyankar if (event->status == TSEVENT_RESET_NEXTSTEP) { 3732d5bd56dSLisandro Dalcin /* Restore time step */ 3742d5bd56dSLisandro Dalcin dt = PetscMin(event->timestep_orig,event->timestep_prev); 3757dbe0728SLisandro Dalcin ierr = TSSetTimeStep(ts,dt);CHKERRQ(ierr); 3762dc7a7e3SShri Abhyankar event->status = TSEVENT_NONE; 3772dc7a7e3SShri Abhyankar } 3782dc7a7e3SShri Abhyankar 3792dc7a7e3SShri Abhyankar if (event->status == TSEVENT_NONE) { 3807dbe0728SLisandro Dalcin event->ptime_end = t; 3812dc7a7e3SShri Abhyankar } 3822dc7a7e3SShri Abhyankar 3836427ac75SLisandro Dalcin ierr = (*event->eventhandler)(ts,t,U,event->fvalue,event->ctx);CHKERRQ(ierr); 3849e12be75SShri Abhyankar 3852dc7a7e3SShri Abhyankar for (i=0; i < event->nevents; i++) { 386e3005195SShri Abhyankar if (PetscAbsScalar(event->fvalue[i]) < event->vtol[i]) { 3872dc7a7e3SShri Abhyankar event->status = TSEVENT_ZERO; 388e2cdd850SShri Abhyankar event->fvalue_right[i] = event->fvalue[i]; 3899e12be75SShri Abhyankar continue; 390006e6a18SShri Abhyankar } 391d94325d3SShri Abhyankar fvalue_sign = PetscSign(PetscRealPart(event->fvalue[i])); 392d94325d3SShri Abhyankar fvalueprev_sign = PetscSign(PetscRealPart(event->fvalue_prev[i])); 393e3005195SShri Abhyankar if (fvalueprev_sign != 0 && (fvalue_sign != fvalueprev_sign) && (PetscAbsScalar(event->fvalue_prev[i]) > event->vtol[i])) { 394d94325d3SShri Abhyankar switch (event->direction[i]) { 395d94325d3SShri Abhyankar case -1: 396d94325d3SShri Abhyankar if (fvalue_sign < 0) { 3972dc7a7e3SShri Abhyankar rollback = 1; 398e2cdd850SShri Abhyankar 399e2cdd850SShri Abhyankar /* Compute new time step */ 400e2cdd850SShri 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); 401e2cdd850SShri Abhyankar 4026427ac75SLisandro Dalcin if (event->monitor) { 40338bf2713SShri 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); 404006e6a18SShri Abhyankar } 405e2cdd850SShri Abhyankar event->fvalue_right[i] = event->fvalue[i]; 406e2cdd850SShri Abhyankar event->side[i] = 1; 407e2cdd850SShri Abhyankar 408e2cdd850SShri Abhyankar if (!event->iterctr) event->zerocrossing[i] = PETSC_TRUE; 409e2cdd850SShri Abhyankar event->status = TSEVENT_LOCATED_INTERVAL; 4102dc7a7e3SShri Abhyankar } 411d94325d3SShri Abhyankar break; 412d94325d3SShri Abhyankar case 1: 413d94325d3SShri Abhyankar if (fvalue_sign > 0) { 414d94325d3SShri Abhyankar rollback = 1; 415e2cdd850SShri Abhyankar 416e2cdd850SShri Abhyankar /* Compute new time step */ 417e2cdd850SShri 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); 418e2cdd850SShri Abhyankar 4196427ac75SLisandro Dalcin if (event->monitor) { 42038bf2713SShri 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); 421006e6a18SShri Abhyankar } 422e2cdd850SShri Abhyankar event->fvalue_right[i] = event->fvalue[i]; 423e2cdd850SShri Abhyankar event->side[i] = 1; 424e2cdd850SShri Abhyankar 425e2cdd850SShri Abhyankar if (!event->iterctr) event->zerocrossing[i] = PETSC_TRUE; 426e2cdd850SShri Abhyankar event->status = TSEVENT_LOCATED_INTERVAL; 4272dc7a7e3SShri Abhyankar } 428d94325d3SShri Abhyankar break; 429d94325d3SShri Abhyankar case 0: 430d94325d3SShri 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; 443e2cdd850SShri Abhyankar 444d94325d3SShri Abhyankar break; 445d94325d3SShri Abhyankar } 446d94325d3SShri Abhyankar } 447d94325d3SShri Abhyankar } 4487dbe0728SLisandro Dalcin 4492589fa24SLisandro Dalcin in[0] = event->status; in[1] = rollback; 4507dbe0728SLisandro Dalcin ierr = MPIU_Allreduce(in,out,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr); 4512589fa24SLisandro Dalcin event->status = (TSEventStatus)out[0]; rollback = out[1]; 4522589fa24SLisandro Dalcin if (rollback) event->status = TSEVENT_LOCATED_INTERVAL; 4532dc7a7e3SShri Abhyankar 4547dbe0728SLisandro Dalcin event->nevents_zero = 0; 4559e12be75SShri Abhyankar if (event->status == TSEVENT_ZERO) { 4569e12be75SShri Abhyankar for (i=0; i < event->nevents; i++) { 4579e12be75SShri Abhyankar if (PetscAbsScalar(event->fvalue[i]) < event->vtol[i]) { 4589e12be75SShri Abhyankar event->events_zero[event->nevents_zero++] = i; 4596427ac75SLisandro Dalcin if (event->monitor) { 46038bf2713SShri 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); 4619e12be75SShri Abhyankar } 462e2cdd850SShri Abhyankar event->zerocrossing[i] = PETSC_FALSE; 4639e12be75SShri Abhyankar } 464e2cdd850SShri Abhyankar event->side[i] = 0; 4659e12be75SShri Abhyankar } 4664597913aSLisandro Dalcin ierr = TSPostEvent(ts,t,U);CHKERRQ(ierr); 4679e12be75SShri Abhyankar 468e2cdd850SShri Abhyankar dt = event->ptime_end - t; 4692d5bd56dSLisandro Dalcin if (PetscAbsReal(dt) < PETSC_SMALL) dt += PetscMin(event->timestep_orig,event->timestep_prev); /* XXX Should be done better */ 4709e12be75SShri Abhyankar ierr = TSSetTimeStep(ts,dt);CHKERRQ(ierr); 47138bf2713SShri Abhyankar event->iterctr = 0; 4729e12be75SShri Abhyankar PetscFunctionReturn(0); 4739e12be75SShri Abhyankar } 4749e12be75SShri Abhyankar 4752dc7a7e3SShri Abhyankar if (event->status == TSEVENT_LOCATED_INTERVAL) { 4762dc7a7e3SShri Abhyankar ierr = TSRollBack(ts);CHKERRQ(ierr); 4772589fa24SLisandro Dalcin ierr = TSSetConvergedReason(ts,TS_CONVERGED_ITERATING);CHKERRQ(ierr); 4782dc7a7e3SShri Abhyankar event->status = TSEVENT_PROCESSING; 479e2cdd850SShri Abhyankar event->ptime_right = t; 4802dc7a7e3SShri Abhyankar } else { 4812dc7a7e3SShri Abhyankar for (i=0; i < event->nevents; i++) { 482e2cdd850SShri Abhyankar if (event->status == TSEVENT_PROCESSING && event->zerocrossing[i]) { 483e2cdd850SShri Abhyankar /* Compute new time step */ 484e2cdd850SShri 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); 485e2cdd850SShri Abhyankar event->side[i] = -1; 486e2cdd850SShri Abhyankar } 4872dc7a7e3SShri Abhyankar event->fvalue_prev[i] = event->fvalue[i]; 4882dc7a7e3SShri Abhyankar } 489e2cdd850SShri Abhyankar if (event->monitor && event->status == TSEVENT_PROCESSING) { 49038bf2713SShri 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); 4912dc7a7e3SShri Abhyankar } 49238bf2713SShri Abhyankar event->ptime_prev = t; 49338bf2713SShri Abhyankar } 49438bf2713SShri Abhyankar 49538bf2713SShri Abhyankar if (event->status == TSEVENT_PROCESSING) event->iterctr++; 4969e12be75SShri Abhyankar 4977dbe0728SLisandro Dalcin ierr = MPIU_Allreduce(&dt,&dt_min,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr); 4987dbe0728SLisandro Dalcin ierr = TSSetTimeStep(ts,dt_min);CHKERRQ(ierr); 4992dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 5002dc7a7e3SShri Abhyankar } 5012dc7a7e3SShri Abhyankar 502d0578d90SShri Abhyankar #undef __FUNCT__ 5036427ac75SLisandro Dalcin #define __FUNCT__ "TSAdjointEventHandler" 5046427ac75SLisandro Dalcin PetscErrorCode TSAdjointEventHandler(TS ts) 505d0578d90SShri Abhyankar { 506d0578d90SShri Abhyankar PetscErrorCode ierr; 5076427ac75SLisandro Dalcin TSEvent event; 508d0578d90SShri Abhyankar PetscReal t; 509d0578d90SShri Abhyankar Vec U; 510d0578d90SShri Abhyankar PetscInt ctr; 511d0578d90SShri Abhyankar PetscBool forwardsolve=PETSC_FALSE; /* Flag indicating that TS is doing an adjoint solve */ 512d0578d90SShri Abhyankar 513d0578d90SShri Abhyankar PetscFunctionBegin; 5146427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 5156427ac75SLisandro Dalcin if (!ts->event) PetscFunctionReturn(0); 5166427ac75SLisandro Dalcin event = ts->event; 517d0578d90SShri Abhyankar 518d0578d90SShri Abhyankar ierr = TSGetTime(ts,&t);CHKERRQ(ierr); 519d0578d90SShri Abhyankar ierr = TSGetSolution(ts,&U);CHKERRQ(ierr); 520d0578d90SShri Abhyankar 521d0578d90SShri Abhyankar ctr = event->recorder.ctr-1; 522bcbf8bb3SShri Abhyankar if (ctr >= 0 && PetscAbsReal(t - event->recorder.time[ctr]) < PETSC_SMALL) { 523d0578d90SShri Abhyankar /* Call the user postevent function */ 524d0578d90SShri Abhyankar if (event->postevent) { 5256427ac75SLisandro Dalcin ierr = (*event->postevent)(ts,event->recorder.nevents[ctr],event->recorder.eventidx[ctr],t,U,forwardsolve,event->ctx);CHKERRQ(ierr); 526d0578d90SShri Abhyankar event->recorder.ctr--; 527d0578d90SShri Abhyankar } 528d0578d90SShri Abhyankar } 529d0578d90SShri Abhyankar 530d0578d90SShri Abhyankar PetscBarrier((PetscObject)ts); 531d0578d90SShri Abhyankar PetscFunctionReturn(0); 532d0578d90SShri Abhyankar } 533