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 46a4ffd976SShri Abhyankar for (i=0; i < (*event)->recsize; i++) { 477dbe0728SLisandro Dalcin ierr = PetscFree((*event)->recorder.eventidx[i]);CHKERRQ(ierr); 487dbe0728SLisandro Dalcin } 49a4ffd976SShri Abhyankar ierr = PetscFree((*event)->recorder.eventidx);CHKERRQ(ierr); 50a4ffd976SShri Abhyankar ierr = PetscFree((*event)->recorder.nevents);CHKERRQ(ierr); 51a4ffd976SShri Abhyankar ierr = PetscFree((*event)->recorder.stepnum);CHKERRQ(ierr); 52a4ffd976SShri Abhyankar ierr = PetscFree((*event)->recorder.time);CHKERRQ(ierr); 53a4ffd976SShri Abhyankar 547dbe0728SLisandro Dalcin ierr = PetscViewerDestroy(&(*event)->monitor);CHKERRQ(ierr); 557dbe0728SLisandro Dalcin ierr = PetscFree(*event);CHKERRQ(ierr); 567dbe0728SLisandro Dalcin PetscFunctionReturn(0); 577dbe0728SLisandro Dalcin } 587dbe0728SLisandro Dalcin 597dbe0728SLisandro Dalcin #undef __FUNCT__ 60e3005195SShri Abhyankar #define __FUNCT__ "TSSetEventTolerances" 61e3005195SShri Abhyankar /*@ 62e3005195SShri Abhyankar TSSetEventTolerances - Set tolerances for event zero crossings when using event handler 63e3005195SShri Abhyankar 64e3005195SShri Abhyankar Logically Collective 65e3005195SShri Abhyankar 66e3005195SShri Abhyankar Input Arguments: 67e3005195SShri Abhyankar + ts - time integration context 68e3005195SShri Abhyankar . tol - scalar tolerance, PETSC_DECIDE to leave current value 69e3005195SShri Abhyankar - vtol - array of tolerances or NULL, used in preference to tol if present 70e3005195SShri Abhyankar 712589fa24SLisandro Dalcin Options Database Keys: 722589fa24SLisandro Dalcin . -ts_event_tol <tol> tolerance for event zero crossing 73e3005195SShri Abhyankar 74e3005195SShri Abhyankar Notes: 75f25fe674SLisandro Dalcin Must call TSSetEventHandler() before setting the tolerances. 76e3005195SShri Abhyankar 77e3005195SShri Abhyankar The size of vtol is equal to the number of events. 78e3005195SShri Abhyankar 79e3005195SShri Abhyankar Level: beginner 80e3005195SShri Abhyankar 81f25fe674SLisandro Dalcin .seealso: TS, TSEvent, TSSetEventHandler() 82e3005195SShri Abhyankar @*/ 836427ac75SLisandro Dalcin PetscErrorCode TSSetEventTolerances(TS ts,PetscReal tol,PetscReal vtol[]) 84e3005195SShri Abhyankar { 856427ac75SLisandro Dalcin TSEvent event; 86e3005195SShri Abhyankar PetscInt i; 87e3005195SShri Abhyankar 88e3005195SShri Abhyankar PetscFunctionBegin; 896427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 906427ac75SLisandro Dalcin if (vtol) PetscValidRealPointer(vtol,3); 91f25fe674SLisandro Dalcin if (!ts->event) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must set the events first by calling TSSetEventHandler()"); 926427ac75SLisandro Dalcin 936427ac75SLisandro Dalcin event = ts->event; 94e3005195SShri Abhyankar if (vtol) { 95e3005195SShri Abhyankar for (i=0; i < event->nevents; i++) event->vtol[i] = vtol[i]; 96e3005195SShri Abhyankar } else { 97e3005195SShri Abhyankar if (tol != PETSC_DECIDE || tol != PETSC_DEFAULT) { 98e3005195SShri Abhyankar for (i=0; i < event->nevents; i++) event->vtol[i] = tol; 99e3005195SShri Abhyankar } 100e3005195SShri Abhyankar } 101e3005195SShri Abhyankar PetscFunctionReturn(0); 102e3005195SShri Abhyankar } 103e3005195SShri Abhyankar 104e3005195SShri Abhyankar #undef __FUNCT__ 105f25fe674SLisandro Dalcin #define __FUNCT__ "TSSetEventHandler" 1062dc7a7e3SShri Abhyankar /*@C 107f25fe674SLisandro Dalcin TSSetEventHandler - Sets a monitoring function used for detecting events 1082dc7a7e3SShri Abhyankar 1092dc7a7e3SShri Abhyankar Logically Collective on TS 1102dc7a7e3SShri Abhyankar 1112dc7a7e3SShri Abhyankar Input Parameters: 1122dc7a7e3SShri Abhyankar + ts - the TS context obtained from TSCreate() 1132dc7a7e3SShri Abhyankar . nevents - number of local events 114d94325d3SShri Abhyankar . direction - direction of zero crossing to be detected. -1 => Zero crossing in negative direction, 115d94325d3SShri Abhyankar +1 => Zero crossing in positive direction, 0 => both ways (one for each event) 116d94325d3SShri Abhyankar . terminate - flag to indicate whether time stepping should be terminated after 117d94325d3SShri Abhyankar event is detected (one for each event) 1186427ac75SLisandro Dalcin . eventhandler - event monitoring routine 1192dc7a7e3SShri Abhyankar . postevent - [optional] post-event function 1202589fa24SLisandro Dalcin - ctx - [optional] user-defined context for private data for the 1212dc7a7e3SShri Abhyankar event monitor and post event routine (use NULL if no 1222dc7a7e3SShri Abhyankar context is desired) 1232dc7a7e3SShri Abhyankar 1246427ac75SLisandro Dalcin Calling sequence of eventhandler: 1252589fa24SLisandro Dalcin PetscErrorCode EventHandler(TS ts,PetscReal t,Vec U,PetscScalar fvalue[],void* ctx) 1262dc7a7e3SShri Abhyankar 1272dc7a7e3SShri Abhyankar Input Parameters: 1282dc7a7e3SShri Abhyankar + ts - the TS context 1292dc7a7e3SShri Abhyankar . t - current time 1302dc7a7e3SShri Abhyankar . U - current iterate 1316427ac75SLisandro Dalcin - ctx - [optional] context passed with eventhandler 1322dc7a7e3SShri Abhyankar 1332dc7a7e3SShri Abhyankar Output parameters: 134d94325d3SShri Abhyankar . fvalue - function value of events at time t 1352dc7a7e3SShri Abhyankar 1362dc7a7e3SShri Abhyankar Calling sequence of postevent: 1372589fa24SLisandro Dalcin PetscErrorCode PostEvent(TS ts,PetscInt nevents_zero, PetscInt events_zero[], PetscReal t,Vec U,PetscBool forwardsolve,void* ctx) 1382dc7a7e3SShri Abhyankar 1392dc7a7e3SShri Abhyankar Input Parameters: 1402dc7a7e3SShri Abhyankar + ts - the TS context 1412dc7a7e3SShri Abhyankar . nevents_zero - number of local events whose event function is zero 1422dc7a7e3SShri Abhyankar . events_zero - indices of local events which have reached zero 1432dc7a7e3SShri Abhyankar . t - current time 1442dc7a7e3SShri Abhyankar . U - current solution 145031fbad4SShri Abhyankar . forwardsolve - Flag to indicate whether TS is doing a forward solve (1) or adjoint solve (0) 1466427ac75SLisandro Dalcin - ctx - the context passed with eventhandler 1472dc7a7e3SShri Abhyankar 1482dc7a7e3SShri Abhyankar Level: intermediate 1492dc7a7e3SShri Abhyankar 1502dc7a7e3SShri Abhyankar .keywords: TS, event, set, monitor 1512dc7a7e3SShri Abhyankar 1522dc7a7e3SShri Abhyankar .seealso: TSCreate(), TSSetTimeStep(), TSSetConvergedReason() 1532dc7a7e3SShri Abhyankar @*/ 1542589fa24SLisandro 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) 1552dc7a7e3SShri Abhyankar { 1562dc7a7e3SShri Abhyankar PetscErrorCode ierr; 1572dc7a7e3SShri Abhyankar TSEvent event; 158d94325d3SShri Abhyankar PetscInt i; 159006e6a18SShri Abhyankar PetscBool flg; 160e3005195SShri Abhyankar PetscReal tol=1e-6; 1612dc7a7e3SShri Abhyankar 1622dc7a7e3SShri Abhyankar PetscFunctionBegin; 1636427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1646427ac75SLisandro Dalcin PetscValidIntPointer(direction,2); 1656427ac75SLisandro Dalcin PetscValidIntPointer(terminate,3); 1666427ac75SLisandro Dalcin 1676427ac75SLisandro Dalcin ierr = PetscNewLog(ts,&event);CHKERRQ(ierr); 168854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->fvalue);CHKERRQ(ierr); 169854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->fvalue_prev);CHKERRQ(ierr); 170e2cdd850SShri Abhyankar ierr = PetscMalloc1(nevents,&event->fvalue_right);CHKERRQ(ierr); 171e2cdd850SShri Abhyankar ierr = PetscMalloc1(nevents,&event->zerocrossing);CHKERRQ(ierr); 172e2cdd850SShri Abhyankar ierr = PetscMalloc1(nevents,&event->side);CHKERRQ(ierr); 173854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->direction);CHKERRQ(ierr); 174854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->terminate);CHKERRQ(ierr); 175e3005195SShri Abhyankar ierr = PetscMalloc1(nevents,&event->vtol);CHKERRQ(ierr); 176d94325d3SShri Abhyankar for (i=0; i < nevents; i++) { 177d94325d3SShri Abhyankar event->direction[i] = direction[i]; 178d94325d3SShri Abhyankar event->terminate[i] = terminate[i]; 179e2cdd850SShri Abhyankar event->zerocrossing[i] = PETSC_FALSE; 180e2cdd850SShri Abhyankar event->side[i] = 0; 181d94325d3SShri Abhyankar } 182854ce69bSBarry Smith ierr = PetscMalloc1(nevents,&event->events_zero);CHKERRQ(ierr); 1832589fa24SLisandro Dalcin event->nevents = nevents; 1846427ac75SLisandro Dalcin event->eventhandler = eventhandler; 1852dc7a7e3SShri Abhyankar event->postevent = postevent; 1866427ac75SLisandro Dalcin event->ctx = ctx; 1872dc7a7e3SShri Abhyankar 188a4ffd976SShri Abhyankar event->recsize = 12; /* Initial size of the recorder */ 189a9514d71SShri Abhyankar ierr = PetscOptionsBegin(((PetscObject)ts)->comm,"","TS Event options","");CHKERRQ(ierr); 1902dc7a7e3SShri Abhyankar { 191e3005195SShri Abhyankar ierr = PetscOptionsReal("-ts_event_tol","Scalar event tolerance for zero crossing check","",tol,&tol,NULL);CHKERRQ(ierr); 192006e6a18SShri Abhyankar ierr = PetscOptionsName("-ts_event_monitor","Print choices made by event handler","",&flg);CHKERRQ(ierr); 193a4ffd976SShri Abhyankar ierr = PetscOptionsInt("-ts_event_recorder_initial_size","Initial size of event recorder","",event->recsize,&event->recsize,NULL);CHKERRQ(ierr); 1942dc7a7e3SShri Abhyankar } 1959e12be75SShri Abhyankar PetscOptionsEnd(); 196a4ffd976SShri Abhyankar 197a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.time);CHKERRQ(ierr); 198a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.stepnum);CHKERRQ(ierr); 199a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.nevents);CHKERRQ(ierr); 200a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->recsize,&event->recorder.eventidx);CHKERRQ(ierr); 201a4ffd976SShri Abhyankar for (i=0; i < event->recsize; i++) { 202a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->nevents,&event->recorder.eventidx[i]);CHKERRQ(ierr); 203a4ffd976SShri Abhyankar } 204a4ffd976SShri Abhyankar 205e3005195SShri Abhyankar for (i=0; i < event->nevents; i++) event->vtol[i] = tol; 2066427ac75SLisandro Dalcin if (flg) {ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,"stdout",&event->monitor);CHKERRQ(ierr);} 2079e12be75SShri Abhyankar 2086427ac75SLisandro Dalcin ierr = TSEventDestroy(&ts->event);CHKERRQ(ierr); 209d94325d3SShri Abhyankar ts->event = event; 2102dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 2112dc7a7e3SShri Abhyankar } 2122dc7a7e3SShri Abhyankar 213a4ffd976SShri Abhyankar #undef __FUNCT__ 214a4ffd976SShri Abhyankar #define __FUNCT__ "TSEventRecorderResize" 215a4ffd976SShri Abhyankar /* 216a4ffd976SShri Abhyankar TSEventRecorderResize - Resizes (2X) the event recorder arrays whenever the recording limit (event->recsize) 217a4ffd976SShri Abhyankar is reached. 218a4ffd976SShri Abhyankar */ 219a4ffd976SShri Abhyankar PetscErrorCode TSEventRecorderResize(TSEvent event) 220a4ffd976SShri Abhyankar { 221a4ffd976SShri Abhyankar PetscErrorCode ierr; 222a4ffd976SShri Abhyankar PetscReal *time; 223a4ffd976SShri Abhyankar PetscInt *stepnum; 224a4ffd976SShri Abhyankar PetscInt *nevents; 225a4ffd976SShri Abhyankar PetscInt **eventidx; 226a4ffd976SShri Abhyankar PetscInt i,fact=2; 227a4ffd976SShri Abhyankar 228a4ffd976SShri Abhyankar PetscFunctionBegin; 229a4ffd976SShri Abhyankar 230a4ffd976SShri Abhyankar /* Create large arrays */ 231a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&time);CHKERRQ(ierr); 232a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&stepnum);CHKERRQ(ierr); 233a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&nevents);CHKERRQ(ierr); 234a4ffd976SShri Abhyankar ierr = PetscMalloc1(fact*event->recsize,&eventidx);CHKERRQ(ierr); 235a4ffd976SShri Abhyankar for (i=0; i < fact*event->recsize; i++) { 236a4ffd976SShri Abhyankar ierr = PetscMalloc1(event->nevents,&eventidx[i]);CHKERRQ(ierr); 237a4ffd976SShri Abhyankar } 238a4ffd976SShri Abhyankar 239a4ffd976SShri Abhyankar /* Copy over data */ 240a4ffd976SShri Abhyankar ierr = PetscMemcpy(time,event->recorder.time,event->recsize*sizeof(PetscReal));CHKERRQ(ierr); 241a4ffd976SShri Abhyankar ierr = PetscMemcpy(stepnum,event->recorder.stepnum,event->recsize*sizeof(PetscInt));CHKERRQ(ierr); 242a4ffd976SShri Abhyankar ierr = PetscMemcpy(nevents,event->recorder.nevents,event->recsize*sizeof(PetscInt));CHKERRQ(ierr); 243a4ffd976SShri Abhyankar for(i=0; i < event->recsize; i++) { 244a4ffd976SShri Abhyankar ierr = PetscMemcpy(eventidx[i],event->recorder.eventidx[i],event->recorder.nevents[i]*sizeof(PetscInt));CHKERRQ(ierr); 245a4ffd976SShri Abhyankar } 246a4ffd976SShri Abhyankar 247a4ffd976SShri Abhyankar /* Destroy old arrays */ 248a4ffd976SShri Abhyankar for (i=0; i < event->recsize; i++) { 249a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.eventidx[i]);CHKERRQ(ierr); 250a4ffd976SShri Abhyankar } 251a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.eventidx);CHKERRQ(ierr); 252a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.nevents);CHKERRQ(ierr); 253a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.stepnum);CHKERRQ(ierr); 254a4ffd976SShri Abhyankar ierr = PetscFree(event->recorder.time);CHKERRQ(ierr); 255a4ffd976SShri Abhyankar 256a4ffd976SShri Abhyankar /* Set pointers */ 257a4ffd976SShri Abhyankar event->recorder.time = time; 258a4ffd976SShri Abhyankar event->recorder.stepnum = stepnum; 259a4ffd976SShri Abhyankar event->recorder.nevents = nevents; 260a4ffd976SShri Abhyankar event->recorder.eventidx = eventidx; 261a4ffd976SShri Abhyankar 262a4ffd976SShri Abhyankar /* Double size */ 263a4ffd976SShri Abhyankar event->recsize *= fact; 264a4ffd976SShri Abhyankar 265a4ffd976SShri Abhyankar PetscFunctionReturn(0); 266a4ffd976SShri Abhyankar } 267a4ffd976SShri Abhyankar 268031fbad4SShri Abhyankar /* 2694597913aSLisandro Dalcin Helper rutine to handle user postenvents and recording 270031fbad4SShri Abhyankar */ 271031fbad4SShri Abhyankar #undef __FUNCT__ 272031fbad4SShri Abhyankar #define __FUNCT__ "TSPostEvent" 2734597913aSLisandro Dalcin static PetscErrorCode TSPostEvent(TS ts,PetscReal t,Vec U) 2742dc7a7e3SShri Abhyankar { 2752dc7a7e3SShri Abhyankar PetscErrorCode ierr; 2762dc7a7e3SShri Abhyankar TSEvent event = ts->event; 2772dc7a7e3SShri Abhyankar PetscBool terminate = PETSC_FALSE; 278d0578d90SShri Abhyankar PetscInt i,ctr,stepnum; 2792dc7a7e3SShri Abhyankar PetscBool ts_terminate; 2804597913aSLisandro Dalcin PetscBool forwardsolve = PETSC_TRUE; /* Flag indicating that TS is doing a forward solve */ 2812dc7a7e3SShri Abhyankar 2822dc7a7e3SShri Abhyankar PetscFunctionBegin; 2832dc7a7e3SShri Abhyankar if (event->postevent) { 2844597913aSLisandro Dalcin ierr = (*event->postevent)(ts,event->nevents_zero,event->events_zero,t,U,forwardsolve,event->ctx);CHKERRQ(ierr); 2852dc7a7e3SShri Abhyankar } 2864597913aSLisandro Dalcin 2874597913aSLisandro Dalcin /* Handle termination events */ 2884597913aSLisandro Dalcin for (i=0; i < event->nevents_zero; i++) { 2894597913aSLisandro Dalcin terminate = (PetscBool)(terminate || event->terminate[event->events_zero[i]]); 2902dc7a7e3SShri Abhyankar } 291b2566f29SBarry Smith ierr = MPIU_Allreduce(&terminate,&ts_terminate,1,MPIU_BOOL,MPI_LOR,((PetscObject)ts)->comm);CHKERRQ(ierr); 2929e12be75SShri Abhyankar if (ts_terminate) { 2932dc7a7e3SShri Abhyankar ierr = TSSetConvergedReason(ts,TS_CONVERGED_EVENT);CHKERRQ(ierr); 2942dc7a7e3SShri Abhyankar event->status = TSEVENT_NONE; 2952dc7a7e3SShri Abhyankar } else { 2962dc7a7e3SShri Abhyankar event->status = TSEVENT_RESET_NEXTSTEP; 2972dc7a7e3SShri Abhyankar } 298f7aea88cSShri Abhyankar 2994597913aSLisandro Dalcin event->ptime_prev = t; 3004597913aSLisandro Dalcin /* Reset event residual functions as states might get changed by the postevent callback */ 3014597913aSLisandro Dalcin if (event->postevent) {ierr = (*event->eventhandler)(ts,t,U,event->fvalue,event->ctx);CHKERRQ(ierr);} 3024597913aSLisandro Dalcin /* Cache current event residual functions */ 3034597913aSLisandro Dalcin for (i=0; i < event->nevents; i++) event->fvalue_prev[i] = event->fvalue[i]; 3044597913aSLisandro Dalcin 305d0578d90SShri Abhyankar /* Record the event in the event recorder */ 306d0578d90SShri Abhyankar ierr = TSGetTimeStepNumber(ts,&stepnum);CHKERRQ(ierr); 307f7aea88cSShri Abhyankar ctr = event->recorder.ctr; 308a4ffd976SShri Abhyankar if (ctr == event->recsize) { 309a4ffd976SShri Abhyankar ierr = TSEventRecorderResize(event);CHKERRQ(ierr); 310a4ffd976SShri Abhyankar } 311f7aea88cSShri Abhyankar event->recorder.time[ctr] = t; 312d0578d90SShri Abhyankar event->recorder.stepnum[ctr] = stepnum; 3134597913aSLisandro Dalcin event->recorder.nevents[ctr] = event->nevents_zero; 3144597913aSLisandro Dalcin for (i=0; i < event->nevents_zero; i++) event->recorder.eventidx[ctr][i] = event->events_zero[i]; 315f7aea88cSShri Abhyankar event->recorder.ctr++; 3162dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 3172dc7a7e3SShri Abhyankar } 3182dc7a7e3SShri Abhyankar 319e2cdd850SShri Abhyankar /* Uses Anderson-Bjorck variant of regular falsi method */ 320*a3a8645aSShri Abhyankar PETSC_STATIC_INLINE PetscReal TSEventComputeStepSize(PetscReal tleft,PetscReal t, PetscReal tright, PetscScalar fleft, PetscScalar f, PetscScalar fright, PetscInt side,PetscReal dt) 32138bf2713SShri Abhyankar { 322e2cdd850SShri Abhyankar PetscReal scal=1.0; 323e2cdd850SShri Abhyankar if(PetscRealPart(fleft)*PetscRealPart(f) < 0) { 324e2cdd850SShri Abhyankar if(side == 1) { 325e2cdd850SShri Abhyankar scal = 1.0 - PetscRealPart(f)/PetscRealPart(fright); 326e2cdd850SShri Abhyankar if(scal < 0) scal = 0.5; 327e2cdd850SShri Abhyankar } 328*a3a8645aSShri Abhyankar dt = PetscMin(dt,(scal*PetscRealPart(fleft)*t - PetscRealPart(f)*tleft)/(scal*PetscRealPart(fleft) - PetscRealPart(f)) - tleft); 329e2cdd850SShri Abhyankar } else { 330e2cdd850SShri Abhyankar if(side == -1) { 331e2cdd850SShri Abhyankar scal = 1.0 - PetscRealPart(f)/PetscRealPart(fleft); 332e2cdd850SShri Abhyankar if(scal < 0) scal = 0.5; 333e2cdd850SShri Abhyankar } 334*a3a8645aSShri Abhyankar dt = PetscMin(dt,(PetscRealPart(f)*tright - scal*PetscRealPart(fright)*t)/(PetscRealPart(f) - scal*PetscRealPart(fright)) - t); 335e2cdd850SShri Abhyankar } 33638bf2713SShri Abhyankar return dt; 33738bf2713SShri Abhyankar } 338e2cdd850SShri Abhyankar 33938bf2713SShri Abhyankar 3402dc7a7e3SShri Abhyankar #undef __FUNCT__ 3416427ac75SLisandro Dalcin #define __FUNCT__ "TSEventHandler" 3426427ac75SLisandro Dalcin PetscErrorCode TSEventHandler(TS ts) 3432dc7a7e3SShri Abhyankar { 3442dc7a7e3SShri Abhyankar PetscErrorCode ierr; 3456427ac75SLisandro Dalcin TSEvent event; 3462dc7a7e3SShri Abhyankar PetscReal t; 3472dc7a7e3SShri Abhyankar Vec U; 3482dc7a7e3SShri Abhyankar PetscInt i; 3497dbe0728SLisandro Dalcin PetscReal dt,dt_min; 3502dc7a7e3SShri Abhyankar PetscInt rollback=0,in[2],out[2]; 3519e12be75SShri Abhyankar PetscInt fvalue_sign,fvalueprev_sign; 3522dc7a7e3SShri Abhyankar 3532dc7a7e3SShri Abhyankar PetscFunctionBegin; 3546427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 3556427ac75SLisandro Dalcin if (!ts->event) PetscFunctionReturn(0); 3566427ac75SLisandro Dalcin event = ts->event; 3572dc7a7e3SShri Abhyankar 3582dc7a7e3SShri Abhyankar ierr = TSGetTime(ts,&t);CHKERRQ(ierr); 3597dbe0728SLisandro Dalcin ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr); 3602dc7a7e3SShri Abhyankar ierr = TSGetSolution(ts,&U);CHKERRQ(ierr); 3612dc7a7e3SShri Abhyankar 3627dbe0728SLisandro Dalcin if (event->status == TSEVENT_NONE) { 3637dbe0728SLisandro Dalcin event->timestep_prev = dt; 3647dbe0728SLisandro Dalcin } 3657dbe0728SLisandro Dalcin 3662dc7a7e3SShri Abhyankar if (event->status == TSEVENT_RESET_NEXTSTEP) { 3677dbe0728SLisandro Dalcin /* Restore previous time step */ 3687dbe0728SLisandro Dalcin dt = event->timestep_prev; 3697dbe0728SLisandro Dalcin ierr = TSSetTimeStep(ts,dt);CHKERRQ(ierr); 3702dc7a7e3SShri Abhyankar event->status = TSEVENT_NONE; 3712dc7a7e3SShri Abhyankar } 3722dc7a7e3SShri Abhyankar 3732dc7a7e3SShri Abhyankar if (event->status == TSEVENT_NONE) { 3747dbe0728SLisandro Dalcin event->ptime_end = t; 3752dc7a7e3SShri Abhyankar } 3762dc7a7e3SShri Abhyankar 3776427ac75SLisandro Dalcin ierr = (*event->eventhandler)(ts,t,U,event->fvalue,event->ctx);CHKERRQ(ierr); 3789e12be75SShri Abhyankar 3792dc7a7e3SShri Abhyankar for (i=0; i < event->nevents; i++) { 380e3005195SShri Abhyankar if (PetscAbsScalar(event->fvalue[i]) < event->vtol[i]) { 3812dc7a7e3SShri Abhyankar event->status = TSEVENT_ZERO; 382e2cdd850SShri Abhyankar event->fvalue_right[i] = event->fvalue[i]; 3839e12be75SShri Abhyankar continue; 384006e6a18SShri Abhyankar } 385d94325d3SShri Abhyankar fvalue_sign = PetscSign(PetscRealPart(event->fvalue[i])); 386d94325d3SShri Abhyankar fvalueprev_sign = PetscSign(PetscRealPart(event->fvalue_prev[i])); 387e3005195SShri Abhyankar if (fvalueprev_sign != 0 && (fvalue_sign != fvalueprev_sign) && (PetscAbsScalar(event->fvalue_prev[i]) > event->vtol[i])) { 388d94325d3SShri Abhyankar switch (event->direction[i]) { 389d94325d3SShri Abhyankar case -1: 390d94325d3SShri Abhyankar if (fvalue_sign < 0) { 3912dc7a7e3SShri Abhyankar rollback = 1; 392e2cdd850SShri Abhyankar 393e2cdd850SShri Abhyankar /* Compute new time step */ 394e2cdd850SShri 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); 395e2cdd850SShri Abhyankar 3966427ac75SLisandro Dalcin if (event->monitor) { 39738bf2713SShri 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); 398006e6a18SShri Abhyankar } 399e2cdd850SShri Abhyankar event->fvalue_right[i] = event->fvalue[i]; 400e2cdd850SShri Abhyankar event->side[i] = 1; 401e2cdd850SShri Abhyankar 402e2cdd850SShri Abhyankar if(!event->iterctr) event->zerocrossing[i] = PETSC_TRUE; 403e2cdd850SShri Abhyankar event->status = TSEVENT_LOCATED_INTERVAL; 4042dc7a7e3SShri Abhyankar } 405d94325d3SShri Abhyankar break; 406d94325d3SShri Abhyankar case 1: 407d94325d3SShri Abhyankar if (fvalue_sign > 0) { 408d94325d3SShri Abhyankar rollback = 1; 409e2cdd850SShri Abhyankar 410e2cdd850SShri Abhyankar /* Compute new time step */ 411e2cdd850SShri 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); 412e2cdd850SShri Abhyankar 4136427ac75SLisandro Dalcin if (event->monitor) { 41438bf2713SShri 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); 415006e6a18SShri Abhyankar } 416e2cdd850SShri Abhyankar event->fvalue_right[i] = event->fvalue[i]; 417e2cdd850SShri Abhyankar event->side[i] = 1; 418e2cdd850SShri Abhyankar 419e2cdd850SShri Abhyankar if(!event->iterctr) event->zerocrossing[i] = PETSC_TRUE; 420e2cdd850SShri Abhyankar event->status = TSEVENT_LOCATED_INTERVAL; 4212dc7a7e3SShri Abhyankar } 422d94325d3SShri Abhyankar break; 423d94325d3SShri Abhyankar case 0: 424d94325d3SShri Abhyankar rollback = 1; 425e2cdd850SShri Abhyankar 426e2cdd850SShri Abhyankar /* Compute new time step */ 427e2cdd850SShri 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); 428e2cdd850SShri Abhyankar 4296427ac75SLisandro Dalcin if (event->monitor) { 43038bf2713SShri 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); 431006e6a18SShri Abhyankar } 432e2cdd850SShri Abhyankar event->fvalue_right[i] = event->fvalue[i]; 433e2cdd850SShri Abhyankar event->side[i] = 1; 434e2cdd850SShri Abhyankar 435e2cdd850SShri Abhyankar if(!event->iterctr) event->zerocrossing[i] = PETSC_TRUE; 436e2cdd850SShri Abhyankar event->status = TSEVENT_LOCATED_INTERVAL; 437e2cdd850SShri Abhyankar 438d94325d3SShri Abhyankar break; 439d94325d3SShri Abhyankar } 440d94325d3SShri Abhyankar } 441d94325d3SShri Abhyankar } 4427dbe0728SLisandro Dalcin 4432589fa24SLisandro Dalcin in[0] = event->status; in[1] = rollback; 4447dbe0728SLisandro Dalcin ierr = MPIU_Allreduce(in,out,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr); 4452589fa24SLisandro Dalcin event->status = (TSEventStatus)out[0]; rollback = out[1]; 4462589fa24SLisandro Dalcin if (rollback) event->status = TSEVENT_LOCATED_INTERVAL; 4472dc7a7e3SShri Abhyankar 4487dbe0728SLisandro Dalcin event->nevents_zero = 0; 4499e12be75SShri Abhyankar if (event->status == TSEVENT_ZERO) { 4509e12be75SShri Abhyankar for (i=0; i < event->nevents; i++) { 4519e12be75SShri Abhyankar if (PetscAbsScalar(event->fvalue[i]) < event->vtol[i]) { 4529e12be75SShri Abhyankar event->events_zero[event->nevents_zero++] = i; 4536427ac75SLisandro Dalcin if (event->monitor) { 45438bf2713SShri 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); 4559e12be75SShri Abhyankar } 456e2cdd850SShri Abhyankar event->zerocrossing[i] = PETSC_FALSE; 4579e12be75SShri Abhyankar } 458e2cdd850SShri Abhyankar event->side[i] = 0; 4599e12be75SShri Abhyankar } 4604597913aSLisandro Dalcin ierr = TSPostEvent(ts,t,U);CHKERRQ(ierr); 4619e12be75SShri Abhyankar 462e2cdd850SShri Abhyankar dt = event->ptime_end - t; 4637dbe0728SLisandro Dalcin if (PetscAbsReal(dt) < PETSC_SMALL) dt += event->timestep_prev; /* XXX Should be done better */ 4649e12be75SShri Abhyankar ierr = TSSetTimeStep(ts,dt);CHKERRQ(ierr); 46538bf2713SShri Abhyankar event->iterctr = 0; 4669e12be75SShri Abhyankar PetscFunctionReturn(0); 4679e12be75SShri Abhyankar } 4689e12be75SShri Abhyankar 4692dc7a7e3SShri Abhyankar if (event->status == TSEVENT_LOCATED_INTERVAL) { 4702dc7a7e3SShri Abhyankar ierr = TSRollBack(ts);CHKERRQ(ierr); 471c540466cSShri Abhyankar ts->steps--; 472c540466cSShri Abhyankar ts->total_steps--; 4732589fa24SLisandro Dalcin ierr = TSSetConvergedReason(ts,TS_CONVERGED_ITERATING);CHKERRQ(ierr); 4742dc7a7e3SShri Abhyankar event->status = TSEVENT_PROCESSING; 475e2cdd850SShri Abhyankar 476e2cdd850SShri Abhyankar event->ptime_right = t; 4772dc7a7e3SShri Abhyankar } else { 4782dc7a7e3SShri Abhyankar for(i=0; i < event->nevents; i++) { 479e2cdd850SShri Abhyankar if (event->status == TSEVENT_PROCESSING && event->zerocrossing[i]) { 480e2cdd850SShri Abhyankar /* Compute new time step */ 481e2cdd850SShri 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); 482e2cdd850SShri Abhyankar 483e2cdd850SShri Abhyankar event->side[i] = -1; 484e2cdd850SShri Abhyankar } 4852dc7a7e3SShri Abhyankar event->fvalue_prev[i] = event->fvalue[i]; 4862dc7a7e3SShri Abhyankar } 48738bf2713SShri Abhyankar 488e2cdd850SShri Abhyankar if (event->monitor && event->status == TSEVENT_PROCESSING) { 48938bf2713SShri 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); 4902dc7a7e3SShri Abhyankar } 49138bf2713SShri Abhyankar event->ptime_prev = t; 49238bf2713SShri Abhyankar } 49338bf2713SShri Abhyankar 49438bf2713SShri Abhyankar if(event->status == TSEVENT_PROCESSING) event->iterctr++; 4959e12be75SShri Abhyankar 4967dbe0728SLisandro Dalcin ierr = MPIU_Allreduce(&dt,&dt_min,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr); 4977dbe0728SLisandro Dalcin ierr = TSSetTimeStep(ts,dt_min);CHKERRQ(ierr); 4982dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 4992dc7a7e3SShri Abhyankar } 5002dc7a7e3SShri Abhyankar 501d0578d90SShri Abhyankar #undef __FUNCT__ 5026427ac75SLisandro Dalcin #define __FUNCT__ "TSAdjointEventHandler" 5036427ac75SLisandro Dalcin PetscErrorCode TSAdjointEventHandler(TS ts) 504d0578d90SShri Abhyankar { 505d0578d90SShri Abhyankar PetscErrorCode ierr; 5066427ac75SLisandro Dalcin TSEvent event; 507d0578d90SShri Abhyankar PetscReal t; 508d0578d90SShri Abhyankar Vec U; 509d0578d90SShri Abhyankar PetscInt ctr; 510d0578d90SShri Abhyankar PetscBool forwardsolve=PETSC_FALSE; /* Flag indicating that TS is doing an adjoint solve */ 511d0578d90SShri Abhyankar 512d0578d90SShri Abhyankar PetscFunctionBegin; 5136427ac75SLisandro Dalcin PetscValidHeaderSpecific(ts,TS_CLASSID,1); 5146427ac75SLisandro Dalcin if (!ts->event) PetscFunctionReturn(0); 5156427ac75SLisandro Dalcin event = ts->event; 516d0578d90SShri Abhyankar 517d0578d90SShri Abhyankar ierr = TSGetTime(ts,&t);CHKERRQ(ierr); 518d0578d90SShri Abhyankar ierr = TSGetSolution(ts,&U);CHKERRQ(ierr); 519d0578d90SShri Abhyankar 520d0578d90SShri Abhyankar ctr = event->recorder.ctr-1; 521bcbf8bb3SShri Abhyankar if (ctr >= 0 && PetscAbsReal(t - event->recorder.time[ctr]) < PETSC_SMALL) { 522d0578d90SShri Abhyankar /* Call the user postevent function */ 523d0578d90SShri Abhyankar if (event->postevent) { 5246427ac75SLisandro Dalcin ierr = (*event->postevent)(ts,event->recorder.nevents[ctr],event->recorder.eventidx[ctr],t,U,forwardsolve,event->ctx);CHKERRQ(ierr); 525d0578d90SShri Abhyankar event->recorder.ctr--; 526d0578d90SShri Abhyankar } 527d0578d90SShri Abhyankar } 528d0578d90SShri Abhyankar 529d0578d90SShri Abhyankar PetscBarrier((PetscObject)ts); 530d0578d90SShri Abhyankar PetscFunctionReturn(0); 531d0578d90SShri Abhyankar } 532