1*2dc7a7e3SShri Abhyankar 2*2dc7a7e3SShri Abhyankar #include <petsc-private/tsimpl.h> /*I "petscts.h" I*/ 3*2dc7a7e3SShri Abhyankar 4*2dc7a7e3SShri Abhyankar #undef __FUNCT__ 5*2dc7a7e3SShri Abhyankar #define __FUNCT__ "TSSetEventMonitor" 6*2dc7a7e3SShri Abhyankar /*@C 7*2dc7a7e3SShri Abhyankar TSSetEventMonitor - Sets a monitoring function used for detecting events 8*2dc7a7e3SShri Abhyankar 9*2dc7a7e3SShri Abhyankar Logically Collective on TS 10*2dc7a7e3SShri Abhyankar 11*2dc7a7e3SShri Abhyankar Input Parameters: 12*2dc7a7e3SShri Abhyankar + ts - the TS context obtained from TSCreate() 13*2dc7a7e3SShri Abhyankar . nevents - number of local events 14*2dc7a7e3SShri Abhyankar . eventmonitor - event monitoring routine 15*2dc7a7e3SShri Abhyankar . postevent - [optional] post-event function 16*2dc7a7e3SShri Abhyankar - mectx - [optional] user-defined context for private data for the 17*2dc7a7e3SShri Abhyankar event monitor and post event routine (use NULL if no 18*2dc7a7e3SShri Abhyankar context is desired) 19*2dc7a7e3SShri Abhyankar 20*2dc7a7e3SShri Abhyankar Calling sequence of eventmonitor: 21*2dc7a7e3SShri Abhyankar PetscErrorCode EventMonitor(TS ts,PetscReal t,Vec U,PetscScalar *fvalue,PetscInt *direction,PetscBool *terminate,void* mectx) 22*2dc7a7e3SShri Abhyankar 23*2dc7a7e3SShri Abhyankar Input Parameters: 24*2dc7a7e3SShri Abhyankar + ts - the TS context 25*2dc7a7e3SShri Abhyankar . t - current time 26*2dc7a7e3SShri Abhyankar . U - current iterate 27*2dc7a7e3SShri Abhyankar - ctx - [optional] context passed with eventmonitor 28*2dc7a7e3SShri Abhyankar 29*2dc7a7e3SShri Abhyankar Output parameters: 30*2dc7a7e3SShri Abhyankar + fvalue - function value of events at time t 31*2dc7a7e3SShri Abhyankar . direction - direction of zero crossing to be detected. -1 => Zero crossing in negative direction, 32*2dc7a7e3SShri Abhyankar +1 => Zero crossing in positive direction, 0 => both ways 33*2dc7a7e3SShri Abhyankar - terminate - terminate time stepping after event is detected. 34*2dc7a7e3SShri Abhyankar 35*2dc7a7e3SShri Abhyankar Calling sequence of postevent: 36*2dc7a7e3SShri Abhyankar PetscErrorCode PostEvent(TS ts,PetscInt nevents_zero, PetscInt events_zero, PetscReal t,Vec U,void* ctx) 37*2dc7a7e3SShri Abhyankar 38*2dc7a7e3SShri Abhyankar Input Parameters: 39*2dc7a7e3SShri Abhyankar + ts - the TS context 40*2dc7a7e3SShri Abhyankar . nevents_zero - number of local events whose event function is zero 41*2dc7a7e3SShri Abhyankar . events_zero - indices of local events which have reached zero 42*2dc7a7e3SShri Abhyankar . t - current time 43*2dc7a7e3SShri Abhyankar . U - current solution 44*2dc7a7e3SShri Abhyankar - ctx - the context passed with eventmonitor 45*2dc7a7e3SShri Abhyankar 46*2dc7a7e3SShri Abhyankar Level: intermediate 47*2dc7a7e3SShri Abhyankar 48*2dc7a7e3SShri Abhyankar .keywords: TS, event, set, monitor 49*2dc7a7e3SShri Abhyankar 50*2dc7a7e3SShri Abhyankar .seealso: TSCreate(), TSSetTimeStep(), TSSetConvergedReason() 51*2dc7a7e3SShri Abhyankar @*/ 52*2dc7a7e3SShri Abhyankar PetscErrorCode TSSetEventMonitor(TS ts,PetscInt nevents,PetscErrorCode (*eventmonitor)(TS,PetscReal,Vec,PetscScalar*,PetscInt*,PetscBool*,void*),PetscErrorCode (*postevent)(TS,PetscInt,PetscInt[],PetscReal,Vec,void*),void *mectx) 53*2dc7a7e3SShri Abhyankar { 54*2dc7a7e3SShri Abhyankar PetscErrorCode ierr; 55*2dc7a7e3SShri Abhyankar PetscReal t; 56*2dc7a7e3SShri Abhyankar Vec U; 57*2dc7a7e3SShri Abhyankar TSEvent event; 58*2dc7a7e3SShri Abhyankar 59*2dc7a7e3SShri Abhyankar PetscFunctionBegin; 60*2dc7a7e3SShri Abhyankar ierr = PetscNew(struct _p_TSEvent,&ts->event);CHKERRQ(ierr); 61*2dc7a7e3SShri Abhyankar event = ts->event; 62*2dc7a7e3SShri Abhyankar ierr = PetscMalloc(nevents*sizeof(PetscScalar),&event->fvalue);CHKERRQ(ierr); 63*2dc7a7e3SShri Abhyankar ierr = PetscMalloc(nevents*sizeof(PetscScalar),&event->fvalue_prev);CHKERRQ(ierr); 64*2dc7a7e3SShri Abhyankar ierr = PetscMalloc(nevents*sizeof(PetscBool),&event->terminate);CHKERRQ(ierr); 65*2dc7a7e3SShri Abhyankar ierr = PetscMalloc(nevents*sizeof(PetscInt),&event->direction);CHKERRQ(ierr); 66*2dc7a7e3SShri Abhyankar ierr = PetscMalloc(nevents*sizeof(PetscInt),&event->events_zero);CHKERRQ(ierr); 67*2dc7a7e3SShri Abhyankar event->monitor = eventmonitor; 68*2dc7a7e3SShri Abhyankar event->postevent = postevent; 69*2dc7a7e3SShri Abhyankar event->monitorcontext = (void*)mectx; 70*2dc7a7e3SShri Abhyankar event->nevents = nevents; 71*2dc7a7e3SShri Abhyankar 72*2dc7a7e3SShri Abhyankar ierr = TSGetTime(ts,&t);CHKERRQ(ierr); 73*2dc7a7e3SShri Abhyankar ierr = TSGetTimeStep(ts,&event->initial_timestep);CHKERRQ(ierr); 74*2dc7a7e3SShri Abhyankar ierr = TSGetSolution(ts,&U);CHKERRQ(ierr); 75*2dc7a7e3SShri Abhyankar event->ptime_prev = t; 76*2dc7a7e3SShri Abhyankar ierr = (*event->monitor)(ts,t,U,event->fvalue_prev,event->direction,event->terminate,mectx);CHKERRQ(ierr); 77*2dc7a7e3SShri Abhyankar ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"TS Event options","");CHKERRQ(ierr); 78*2dc7a7e3SShri Abhyankar { 79*2dc7a7e3SShri Abhyankar event->tol = 1.0e-6; 80*2dc7a7e3SShri Abhyankar ierr = PetscOptionsReal("-ts_event_tol","","",event->tol,&event->tol,NULL);CHKERRQ(ierr); 81*2dc7a7e3SShri Abhyankar } 82*2dc7a7e3SShri Abhyankar ierr = PetscOptionsEnd();CHKERRQ(ierr); 83*2dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 84*2dc7a7e3SShri Abhyankar } 85*2dc7a7e3SShri Abhyankar 86*2dc7a7e3SShri Abhyankar #undef __FUNCT__ 87*2dc7a7e3SShri Abhyankar #define __FUNCT__ "TSPostEvent" 88*2dc7a7e3SShri Abhyankar PetscErrorCode TSPostEvent(TS ts,PetscInt nevents_zero,PetscInt events_zero[],PetscReal t,Vec U,void *ctx) 89*2dc7a7e3SShri Abhyankar { 90*2dc7a7e3SShri Abhyankar PetscErrorCode ierr; 91*2dc7a7e3SShri Abhyankar TSEvent event=ts->event; 92*2dc7a7e3SShri Abhyankar PetscBool terminate=PETSC_FALSE; 93*2dc7a7e3SShri Abhyankar PetscInt i; 94*2dc7a7e3SShri Abhyankar PetscBool ts_terminate; 95*2dc7a7e3SShri Abhyankar 96*2dc7a7e3SShri Abhyankar PetscFunctionBegin; 97*2dc7a7e3SShri Abhyankar if (event->postevent) { 98*2dc7a7e3SShri Abhyankar ierr = (*event->postevent)(ts,nevents_zero,events_zero,t,U,ctx);CHKERRQ(ierr); 99*2dc7a7e3SShri Abhyankar } 100*2dc7a7e3SShri Abhyankar for(i = 0; i < nevents_zero;i++) { 101*2dc7a7e3SShri Abhyankar terminate = terminate || event->terminate[events_zero[i]]; 102*2dc7a7e3SShri Abhyankar } 103*2dc7a7e3SShri Abhyankar ierr = MPI_Allreduce(&terminate,&ts_terminate,1,MPIU_INT,MPI_MAX,((PetscObject)ts)->comm);CHKERRQ(ierr); 104*2dc7a7e3SShri Abhyankar if (terminate) { 105*2dc7a7e3SShri Abhyankar ierr = TSSetConvergedReason(ts,TS_CONVERGED_EVENT);CHKERRQ(ierr); 106*2dc7a7e3SShri Abhyankar event->status = TSEVENT_NONE; 107*2dc7a7e3SShri Abhyankar } else { 108*2dc7a7e3SShri Abhyankar event->status = TSEVENT_RESET_NEXTSTEP; 109*2dc7a7e3SShri Abhyankar } 110*2dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 111*2dc7a7e3SShri Abhyankar } 112*2dc7a7e3SShri Abhyankar 113*2dc7a7e3SShri Abhyankar #undef __FUNCT__ 114*2dc7a7e3SShri Abhyankar #define __FUNCT__ "TSEventMonitorDestroy" 115*2dc7a7e3SShri Abhyankar PetscErrorCode TSEventMonitorDestroy(TSEvent *event) 116*2dc7a7e3SShri Abhyankar { 117*2dc7a7e3SShri Abhyankar PetscErrorCode ierr; 118*2dc7a7e3SShri Abhyankar 119*2dc7a7e3SShri Abhyankar PetscFunctionBegin; 120*2dc7a7e3SShri Abhyankar ierr = PetscFree((*event)->fvalue);CHKERRQ(ierr); 121*2dc7a7e3SShri Abhyankar ierr = PetscFree((*event)->fvalue_prev);CHKERRQ(ierr); 122*2dc7a7e3SShri Abhyankar ierr = PetscFree((*event)->terminate);CHKERRQ(ierr); 123*2dc7a7e3SShri Abhyankar ierr = PetscFree((*event)->direction);CHKERRQ(ierr); 124*2dc7a7e3SShri Abhyankar ierr = PetscFree((*event)->events_zero);CHKERRQ(ierr); 125*2dc7a7e3SShri Abhyankar ierr = PetscFree(*event);CHKERRQ(ierr); 126*2dc7a7e3SShri Abhyankar *event = NULL; 127*2dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 128*2dc7a7e3SShri Abhyankar } 129*2dc7a7e3SShri Abhyankar 130*2dc7a7e3SShri Abhyankar #undef __FUNCT__ 131*2dc7a7e3SShri Abhyankar #define __FUNCT__ "TSEventMonitor" 132*2dc7a7e3SShri Abhyankar PetscErrorCode TSEventMonitor(TS ts) 133*2dc7a7e3SShri Abhyankar { 134*2dc7a7e3SShri Abhyankar PetscErrorCode ierr; 135*2dc7a7e3SShri Abhyankar TSEvent event=ts->event; 136*2dc7a7e3SShri Abhyankar PetscReal t; 137*2dc7a7e3SShri Abhyankar Vec U; 138*2dc7a7e3SShri Abhyankar PetscInt i; 139*2dc7a7e3SShri Abhyankar PetscReal dt; 140*2dc7a7e3SShri Abhyankar PetscInt status=event->status; 141*2dc7a7e3SShri Abhyankar PetscInt rollback=0,in[2],out[2]; 142*2dc7a7e3SShri Abhyankar 143*2dc7a7e3SShri Abhyankar PetscFunctionBegin; 144*2dc7a7e3SShri Abhyankar 145*2dc7a7e3SShri Abhyankar ierr = TSGetTime(ts,&t);CHKERRQ(ierr); 146*2dc7a7e3SShri Abhyankar ierr = TSGetSolution(ts,&U);CHKERRQ(ierr); 147*2dc7a7e3SShri Abhyankar 148*2dc7a7e3SShri Abhyankar ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr); 149*2dc7a7e3SShri Abhyankar if (event->status == TSEVENT_RESET_NEXTSTEP) { 150*2dc7a7e3SShri Abhyankar /* Take initial time step */ 151*2dc7a7e3SShri Abhyankar dt = event->initial_timestep; 152*2dc7a7e3SShri Abhyankar ts->time_step = dt; 153*2dc7a7e3SShri Abhyankar event->status = TSEVENT_NONE; 154*2dc7a7e3SShri Abhyankar } 155*2dc7a7e3SShri Abhyankar 156*2dc7a7e3SShri Abhyankar if (event->status == TSEVENT_NONE) { 157*2dc7a7e3SShri Abhyankar event->tstepend = t; 158*2dc7a7e3SShri Abhyankar } 159*2dc7a7e3SShri Abhyankar 160*2dc7a7e3SShri Abhyankar event->nevents_zero = 0; 161*2dc7a7e3SShri Abhyankar 162*2dc7a7e3SShri Abhyankar ierr = (*event->monitor)(ts,t,U,event->fvalue,event->direction,event->terminate,event->monitorcontext);CHKERRQ(ierr); 163*2dc7a7e3SShri Abhyankar if (event->status != TSEVENT_NONE) { 164*2dc7a7e3SShri Abhyankar for (i=0; i < event->nevents; i++) { 165*2dc7a7e3SShri Abhyankar if (PetscAbs(event->fvalue[i]) < event->tol) { 166*2dc7a7e3SShri Abhyankar event->status = TSEVENT_ZERO; 167*2dc7a7e3SShri Abhyankar event->events_zero[event->nevents_zero++] = i; 168*2dc7a7e3SShri Abhyankar } 169*2dc7a7e3SShri Abhyankar } 170*2dc7a7e3SShri Abhyankar } 171*2dc7a7e3SShri Abhyankar 172*2dc7a7e3SShri Abhyankar status = event->status; 173*2dc7a7e3SShri Abhyankar ierr = MPI_Allreduce(&status,&event->status,1,MPIU_INT,MPI_MAX,((PetscObject)ts)->comm);CHKERRQ(ierr); 174*2dc7a7e3SShri Abhyankar 175*2dc7a7e3SShri Abhyankar if (event->status == TSEVENT_ZERO) { 176*2dc7a7e3SShri Abhyankar dt = event->tstepend-t; 177*2dc7a7e3SShri Abhyankar ts->time_step = dt; 178*2dc7a7e3SShri Abhyankar ierr = TSPostEvent(ts,event->nevents_zero,event->events_zero,t,U,event->monitorcontext);CHKERRQ(ierr); 179*2dc7a7e3SShri Abhyankar for (i = 0; i < event->nevents; i++) { 180*2dc7a7e3SShri Abhyankar event->fvalue_prev[i] = event->fvalue[i]; 181*2dc7a7e3SShri Abhyankar } 182*2dc7a7e3SShri Abhyankar event->ptime_prev = t; 183*2dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 184*2dc7a7e3SShri Abhyankar } 185*2dc7a7e3SShri Abhyankar 186*2dc7a7e3SShri Abhyankar for (i = 0; i < event->nevents; i++) { 187*2dc7a7e3SShri Abhyankar if ((event->direction[i] < 0 && PetscSign(event->fvalue[i]) <= 0 && PetscSign(event->fvalue_prev[i]) >= 0) || \ 188*2dc7a7e3SShri Abhyankar (event->direction[i] > 0 && PetscSign(event->fvalue[i]) >= 0 && PetscSign(event->fvalue_prev[i]) <= 0) || \ 189*2dc7a7e3SShri Abhyankar (event->direction[i] == 0 && PetscSign(event->fvalue[i])*PetscSign(event->fvalue_prev[i]) <= 0)) { 190*2dc7a7e3SShri Abhyankar 191*2dc7a7e3SShri Abhyankar event->status = TSEVENT_LOCATED_INTERVAL; 192*2dc7a7e3SShri Abhyankar rollback = 1; 193*2dc7a7e3SShri Abhyankar /* Compute linearly interpolated new time step */ 194*2dc7a7e3SShri Abhyankar dt = PetscMin(dt,-event->fvalue_prev[i]*(t - event->ptime_prev)/(event->fvalue[i] - event->fvalue_prev[i])); 195*2dc7a7e3SShri Abhyankar } 196*2dc7a7e3SShri Abhyankar } 197*2dc7a7e3SShri Abhyankar in[0] = event->status; 198*2dc7a7e3SShri Abhyankar in[1] = rollback; 199*2dc7a7e3SShri Abhyankar ierr = MPI_Allreduce(in,out,2,MPIU_INT,MPI_MAX,((PetscObject)ts)->comm);CHKERRQ(ierr); 200*2dc7a7e3SShri Abhyankar 201*2dc7a7e3SShri Abhyankar rollback = out[1]; 202*2dc7a7e3SShri Abhyankar if (rollback) { 203*2dc7a7e3SShri Abhyankar event->status = TSEVENT_LOCATED_INTERVAL; 204*2dc7a7e3SShri Abhyankar } 205*2dc7a7e3SShri Abhyankar 206*2dc7a7e3SShri Abhyankar if (event->status == TSEVENT_LOCATED_INTERVAL) { 207*2dc7a7e3SShri Abhyankar ierr = TSRollBack(ts);CHKERRQ(ierr); 208*2dc7a7e3SShri Abhyankar event->status = TSEVENT_PROCESSING; 209*2dc7a7e3SShri Abhyankar } else { 210*2dc7a7e3SShri Abhyankar for (i = 0; i < event->nevents; i++) { 211*2dc7a7e3SShri Abhyankar event->fvalue_prev[i] = event->fvalue[i]; 212*2dc7a7e3SShri Abhyankar } 213*2dc7a7e3SShri Abhyankar event->ptime_prev = t; 214*2dc7a7e3SShri Abhyankar if (event->status == TSEVENT_PROCESSING) { 215*2dc7a7e3SShri Abhyankar dt = event->tstepend - event->ptime_prev; 216*2dc7a7e3SShri Abhyankar } 217*2dc7a7e3SShri Abhyankar } 218*2dc7a7e3SShri Abhyankar PetscReal time_step; 219*2dc7a7e3SShri Abhyankar ierr = MPI_Allreduce(&dt,&time_step,1,MPIU_REAL,MPI_MIN,((PetscObject)ts)->comm);CHKERRQ(ierr); 220*2dc7a7e3SShri Abhyankar ts->time_step = time_step; 221*2dc7a7e3SShri Abhyankar PetscFunctionReturn(0); 222*2dc7a7e3SShri Abhyankar } 223*2dc7a7e3SShri Abhyankar 224