/** * Finds root in the interval \f$ [t1,t2] \f$. */ int RootFinder::solve(double t1, double t2, double* root) { switch(method) { case BISECTION: return bisection(t1, t2, root); case BRENTS_METHOD: return brents_method(t1, t2, root); case REGULA_FALSI: return regula_falsi(t1, t2, root); default: return false; } }
int main( int argc, char*argv[]) { int root = 0; double t; double t_test; double t_next; double tgo; double dt = 0.2; REGULA_FALSI rf; reset_regula_falsi(t, &rf); rf.error_tol = 1.0e-15; rf.mode = Any; for (t=0.0; t<15.0; t+=dt) { t_next = t + dt; t_test = t; rf.error = sin( t_test); tgo = regula_falsi(t_test, &rf); while ( ( (t_test + tgo) < t_next) && !root) { t_test += tgo; rf.error = sin( t_test); tgo = regula_falsi(t_test, &rf); if (fabs(tgo) < rf.error_tol) { printf("ROOT @ %18.14g\n", t_test); root = 1; reset_regula_falsi(t_test, &rf); } } root = 0; } exit(0); }
/* The cannonball sim's dynamic job */ double cannon_impact( CANNON* C ) { double tgo ; /* time-to-go */ double now ; /* current integration time. */ C->rf.error = C->pos[1] ; /* Specify the event boundary. */ now = get_integ_time() ; /* Get the current integration time */ tgo = regula_falsi( now, &(C->rf) ) ; /* Estimate remaining integration time. */ if (tgo == 0.0) { /* If we are at the event, it's action time! */ now = get_integ_time() ; reset_regula_falsi( now, &(C->rf) ) ; C->impact = 1 ; C->impactTime = now ; C->vel[0] = 0.0 ; C->vel[1] = 0.0 ; C->acc[0] = 0.0 ; C->acc[1] = 0.0 ; fprintf(stderr, "\n\nIMPACT: SimTime = %.9f, pos = %.9f\n\n", now, C->pos[0] ) ; } return (tgo) ; }
int sweep_regula_falsi(double (*func)(double x),double xstart,double xstop,double xinc,int nmax,double tol) { double a,b,fa,fb; int retval; xstop = xstop + (xinc * 0.5); a = xstart; fa = (*func)(a); b = a + xinc; while (((xinc > 0.0) && (b < xstop)) || ((xinc < 0.0) && (b > xstop))) { fb = (*func)(b); if ((fa * fb) < 0.0) { /*root bracketed, converge with regula_falsi*/ retval = regula_falsi(func,a,b,nmax,tol); if (retval > 0) return(retval); } a = b; fa = fb; b = b + xinc; } return(0); }
double sched_dyn_event( /* RETURN: s Time to go to event */ SCHEDULE * S) /* INOUT: -- */ { double tgo; /* Estimated time to go (in seconds) to the defined event */ double now = get_integ_time(); /* CALCULATE TIME TO GO FOR EVENT */ S->rf.error = S->mass - 1.2; tgo = regula_falsi( now , &(S->rf) ); if ( tgo == 0.0 ) { /* FIRE EVENT */ reset_regula_falsi( now , &(S->rf) ); /* Make mass zig zag once it hits 1.2kg */ S->mass = S->mass - 0.01; } return( tgo ) ; }
void IBall_sim( Integrator_type Alg, std::ostream& dataout) { BALL ball; long tick; double sim_time; REGULA_FALSI rf; const double seconds_per_tick = 0.01; const double initial_angle = 30.0; const double initial_speed = 50.0; const int doing_dynamic_events = 1; dataout.width(16); dataout.precision(14); // ======================================== // Initialization // ======================================== tick = 0; sim_time = 0.0; ball.pos[0] = 0.0; ball.pos[1] = 0.0; ball.vel[0] = initial_speed * cos( initial_angle * RAD_PER_DEG); ball.vel[1] = initial_speed * sin( initial_angle * RAD_PER_DEG); Trick::Integrator *I = Trick::getIntegrator( Alg, 4, seconds_per_tick ); sim_time = tick * seconds_per_tick ; // Initialize Regula Falsi. reset_regula_falsi(sim_time, &rf); rf.error_tol = 1.0e-15; rf.mode = Any; // Note: We don't care what the tgo estimate is because here, // we are just initializing the bounds. rf.error = ball.pos[0]; regula_falsi(sim_time, &rf); // ======================================== // Simulation loop // ======================================== do { dataout << sim_time << " " << ball.pos[0] << " " << ball.pos[1] << std::endl; I->time = sim_time; // ###I### Integrate over the time step. integ(I, &ball); // Advance time. tick++; sim_time = tick * seconds_per_tick ; // If we are looking for roots ... if ( doing_dynamic_events ) { double tgo; // ###RF### Given the current error, estimate how far (in time) we are from a root. rf.error = ball.pos[0]; tgo = regula_falsi(sim_time, &rf); // If regula_falsi found a root in the last interval ... if ( tgo < seconds_per_tick) { int root_found = 0; double t_test = sim_time; // Iterate until we find the root. // NOTE: the regula_falsi function gives up and returns with tgo=0 if // it hasn't converged on a root after 20 iterations. while (! root_found) { // ###I### Integrate over the time-correction. I->dt = tgo; integ(I, &ball); t_test += tgo; // ###RF### Given the current error, estimate how far (in time) we are from the root. rf.error = ball.pos[0]; tgo = regula_falsi( t_test, &rf); // If the estimated time-to-go is less than the chosen tolerance, then we have our root. if (fabs( tgo) < rf.error_tol) { printf("ROOT@ %18.14g\n", t_test); root_found = 1; reset_regula_falsi(t_test, &rf); } } root_found = 0; // ###I### Integrate from t=t_test back (forward actually) to t=sim_time. I->dt = sim_time - t_test ; integ(I, &ball); // Restore the normal time-step. I->dt = seconds_per_tick; } } // End of doing_dynamic_events. } while (ball.pos[0] >= -3.0); dataout << sim_time << " " << ball.pos[0] << " " << ball.pos[1] << std::endl; delete( I); }