Example #1
0
int main(int argc, char *argv[]) {
    struct particle **arr;
    int dimensions = 1;
    float step = 0.1;
    int num_particles = 2;
    int num_iterations = 10;
    int threads = 1;
    if(argc < 4) {
        fprintf(stderr,"Usage ./particle_simulator #of_particles #of_iterations threads [one_dim / two_dim](default: one_dim)\n");
        //return 1;
    } else {
        num_particles = strtoll(argv[1],NULL,10);
        num_iterations = strtoll(argv[2],NULL,10);
        threads = strtoll(argv[3],NULL,10);
    }
    if(argc > 4 && strcmp(argv[4],"two_dim") == 0) dimensions = 2;
   
    arr =  generate_particles(num_particles);
    int i, j;

    //printf("Iteration, ParticleID, ParticleX, ParticleY\n");
    //print_particles(num_particles,arr,0);
    omp_set_num_threads(threads);
    for(i = 1; i <= num_iterations; i++) {
#pragma omp parallel for
        for(j = 0; j < num_particles; j++) {
            calculate_acceleration(arr[j],num_particles,arr,dimensions);
        }
        for(j = 0; j < num_particles; j++) {
            update_vel_position(arr[j],step);
        }
        //print_particles(num_particles,arr,i);
    }
    free_particles(num_particles,arr);
}
Example #2
0
/**
 * Solves the system of ordinary differential equations governing Tux's 
 * movement.  Based on Matlab's ode23.m, (c) The MathWorks, Inc.
 */
static void
solve_ode_system(Player& plyr, float timestep) 
{
    ODESolver x, y, z, vx, vy, vz; // estimates of derivs

    bool done = false;
    float speed;
    float pos_err[3], vel_err[3], tot_pos_err, tot_vel_err;
    float err=0, tol=0;
    int i;
	
    // Select an initial time step
    float h = ode_time_step;

    if(h < 0){
		h = adjust_time_step_size( timestep, plyr.vel );
    }

    float t0 = 0;
    float tfinal = timestep;
    float t = t0;

	// initialize state
    ppogl::Vec3d new_pos = plyr.pos;
    ppogl::Vec3d new_vel = plyr.vel;
    ppogl::Vec3d new_f = plyr.net_force;

    // loop until we've integrated from t0 to tfinal
    while (!done) {

	if ( t >= tfinal ) {
	    PP_WARNING( "t >= tfinal in solve_ode_system()" );
	    break;
	}

	// extend h by up to 10% to reach tfinal
	if ( 1.1 * h > tfinal - t ) {
	    h = tfinal-t;
	    PP_ASSERT( h >= 0., "integrated past tfinal" );
	    done = true;
	}

    PP_LOG( DEBUG_ODE, "h: " << h );

	ppogl::Vec3d saved_pos = new_pos;
	ppogl::Vec3d saved_vel = new_vel;
	ppogl::Vec3d saved_f = new_f;

	// Loop until error is acceptable
	bool failed = false;

	for(;;){
	    // Store initial conditions
	    x.initODEData(new_pos.x(), h);
	    y.initODEData(new_pos.y(), h);
	    z.initODEData(new_pos.z(), h);
	    vx.initODEData(new_vel.x(), h);
	    vy.initODEData(new_vel.y(), h);
	    vz.initODEData(new_vel.z(), h);


	    // We assume that the first estimate in all ODE solvers is equal 
	    // to the final value of the last iteration
		x.updateEstimate(0, new_vel.x());
	    y.updateEstimate(0, new_vel.y());
	    z.updateEstimate(0, new_vel.z());
	    vx.updateEstimate(0, new_f.x() / TUX_MASS);
	    vy.updateEstimate(0, new_f.y() / TUX_MASS);
	    vz.updateEstimate(0, new_f.z() / TUX_MASS);

	    // Update remaining estimates
	    for ( i=1; i < ODESolver::numEstimates(); i++ ) {
		new_pos.x() = x.nextVal(i);
		new_pos.y() = y.nextVal(i);
		new_pos.z() = z.nextVal(i);
		new_vel.x() = vx.nextVal(i);
		new_vel.y() = vy.nextVal(i);
		new_vel.z() = vz.nextVal(i);

		x.updateEstimate(i, new_vel.x());
		y.updateEstimate(i, new_vel.y());
		z.updateEstimate(i, new_vel.z());

		new_f = calc_net_force( plyr, new_pos, new_vel );

		vx.updateEstimate(i, new_f.x() / TUX_MASS);
		vy.updateEstimate(i, new_f.y() / TUX_MASS);
		vz.updateEstimate(i, new_f.z() / TUX_MASS);
	    }

	    // Get final values
	    new_pos.x() = x.finalEstimate();
	    new_pos.y() = y.finalEstimate();
	    new_pos.z() = z.finalEstimate();

	    new_vel.x() = vx.finalEstimate();
	    new_vel.y() = vy.finalEstimate();
	    new_vel.z() = vz.finalEstimate();

		// Calculate the error
		pos_err[0] = x.estimateError();
		pos_err[1] = y.estimateError();
		pos_err[2] = z.estimateError();

		vel_err[0] = vx.estimateError();
		vel_err[1] = vy.estimateError();
		vel_err[2] = vz.estimateError();

		tot_pos_err = 0.;
		tot_vel_err = 0.;
		for ( i=0; i<3; i++ ) {
		    pos_err[i] *= pos_err[i];
		    tot_pos_err += pos_err[i];
		    vel_err[i] *= vel_err[i];
		    tot_vel_err += vel_err[i];
		}
		tot_pos_err = sqrt( tot_pos_err );
		tot_vel_err = sqrt( tot_vel_err );

        PP_LOG(DEBUG_ODE, "pos_err: " << tot_pos_err << ", vel_err: " << tot_vel_err );

		if ( tot_pos_err / MAX_POSITION_ERROR >
		     tot_vel_err / MAX_VELOCITY_ERROR )
		{
		    err = tot_pos_err;
		    tol = MAX_POSITION_ERROR;
		} else {
		    err = tot_vel_err;
		    tol = MAX_VELOCITY_ERROR;
		}

		// Update h based on error
		if (  err > tol  && h > MIN_TIME_STEP + EPS  )
		{
		    done = false;
		    if ( !failed ) {
			failed = true;
			h *=  MAX( 0.5, 0.8 *
				   pow( tol/err, 
					float(ODESolver::timeStepExponent()) ) );
		    } else {
			h *= 0.5;
		    }

		    h = adjust_time_step_size( h, saved_vel );

		    new_pos = saved_pos;
		    new_vel = saved_vel;
		    new_f = saved_f;
		
		} else {
		    // Error is acceptable or h is at its minimum; stop
		    break;
		}
	}

	// Update time
	t = t + h;

	ppogl::Vec3d tmp_vel = new_vel;
	speed = tmp_vel.normalize();

	// only generate particles if we're drawing them
	if(GameConfig::drawParticles){
	    generate_particles( plyr, h, new_pos, speed );
	}

	// Calculate the final net force
	new_f = calc_net_force( plyr, new_pos, new_vel );

	// If no failures, compute a new h
	if(!failed){
		double temp = 1.25 * pow(double(err) / tol,double(ODESolver::timeStepExponent()));
		if ( temp > 0.2 ) {
			h = h / temp;
	    } else {
			h = 5.0 * h;
	    }
	}

	// Clamp h to constraints
	h = adjust_time_step_size( h, new_vel );

	// Important: to make trees "solid", we must manipulate the 
	// velocity here; if we don't and Tux is moving very quickly,
	// he can pass through trees
	adjust_for_model_collision(plyr, new_pos, new_vel);

	// Try to collect items here
	check_item_collection( plyr, new_pos );

    }

    // Save time step for next time
    ode_time_step = h;

    plyr.vel = new_vel;
    plyr.pos = new_pos;
    plyr.net_force = new_f;
}