/*! Updates the interaction matrices with the image plane the camera is facing. The plane must be in the format: \f$ \frac{1}{Z}=Ax+By+C \f$ . The moment primitives MUST be updated before calling this function. This method also computes the interaction matrix. Therefore, you must call vpFeatureMoment::update before calling vpFeatureMoment::interaction. \attention The behaviour of this method is not the same as vpMoment::update which only acknowledges the new object. This method also computes the interaction matrices. \param A : A coefficient of the plane. \param B : B coefficient of the plane. \param C : C coefficient of the plane. */ void vpFeatureMoment::update (double A, double B, double C){ this->A = A; this->B = B; this->C = C; if(moment==NULL){ bool found; this->moment = &(moments.get(momentName(),found)); if(!found) throw ("Moment not found for feature"); } nbParameters = 1; if(this->moment!=NULL){ dim_s = (unsigned int)this->moment->get().size(); s.resize(dim_s); for(unsigned int i=0;i<dim_s;i++) s[i] = this->moment->get()[i]; if (flags == NULL) flags = new bool[nbParameters]; for (unsigned int i = 0; i < nbParameters; i++) flags[i] = false; }else dim_s = 0; compute_interaction(); }
void init_particles(particle* system){ /* * particles will be placed randomly 4 quadrants of 3d space * q1: x>0, y>0 * q2: x<0, y>0 * q3: x<0, y<0 * q4: x>0, y<0 * */ int i = 0; srand(time(NULL)); // q1 x>0, y>0 for(; i < NO_OF_PARTICLES/4; i++){ system[i].position = (__vector float){rand()%INIT_BOUNDING_BOX, rand()%INIT_BOUNDING_BOX, (rand()%INIT_BOUNDING_BOX*2)-INIT_BOUNDING_BOX, 0}; system[i].velocity = VECZERO; system[i].acceleration = VECZERO; } // q2 x<0, y>0 for(; i < NO_OF_PARTICLES/2; i++){ system[i].position = (__vector float){-rand()%INIT_BOUNDING_BOX, rand()%INIT_BOUNDING_BOX, (rand()%INIT_BOUNDING_BOX*2)-INIT_BOUNDING_BOX, 0}; system[i].velocity = VECZERO; system[i].acceleration = VECZERO; } // q3 x<0, y<0 for(; i < 3*NO_OF_PARTICLES/4; i++){ system[i].position = (__vector float){-rand()%INIT_BOUNDING_BOX, -rand()%INIT_BOUNDING_BOX, (rand()%INIT_BOUNDING_BOX*2)-INIT_BOUNDING_BOX, 0}; system[i].velocity = VECZERO; system[i].acceleration = VECZERO; } // q4 x>0, y<0 for(; i < NO_OF_PARTICLES; i++){ system[i].position = (__vector float){rand()%INIT_BOUNDING_BOX, -rand()%INIT_BOUNDING_BOX, (rand()%INIT_BOUNDING_BOX*2)-INIT_BOUNDING_BOX, 0}; system[i].velocity = VECZERO; system[i].acceleration = VECZERO; } } void compute_interaction(particle* i , particle* j){ __vector float radius, radius_sqr, s_vector, displ, accel, distSqr, distSixth, invDistCube; /*compute acceleration of particle i*/ radius = vec_sub(j->position,i->position); radius_sqr = vec_madd(radius,radius, VECZERO); distSqr = vec_add(vec_splat(radius_sqr,0),vec_splat(radius_sqr,1)); distSqr = vec_add(vec_splat(radius_sqr,2),distSqr); distSqr = vec_add(EPS2_VECTOR,distSqr); distSixth = vec_madd(distSqr,distSqr,VECZERO); distSixth = vec_madd(distSixth,distSqr,VEC3ZERO); invDistCube = vec_rsqrte(distSixth); s_vector = vec_madd(MASS_VECTOR,invDistCube,VECZERO); i->acceleration = vec_madd(radius,s_vector,i->acceleration); /*compute new position & velocity of particle i*/ displ = vec_madd(i->velocity,TIME_STEP_VECTOR,i->position); accel = vec_madd(VECHALF,i->acceleration, VECZERO); i->position = vec_madd(accel,TIME_SQUARED, displ); i->velocity = vec_madd(i->acceleration,TIME_STEP_VECTOR, i->velocity); } void update_particles(particle* system){ int i, j; //Thread 1 ? for(i = 0;i<NO_OF_PARTICLES/4;i++){ for(j = 0;j<NO_OF_PARTICLES;j++){ compute_interaction(&system[i],&system[j]); } } //Thread 2 ? for(i = NO_OF_PARTICLES/4;i<NO_OF_PARTICLES/2;i++){ for(j = 0;j<NO_OF_PARTICLES;j++){ compute_interaction(&system[i],&system[j]); } } //Thread 3 ? for(i = NO_OF_PARTICLES/2;i<3*NO_OF_PARTICLES/4;i++){ for(j = 0;j<NO_OF_PARTICLES;j++){ compute_interaction(&system[i],&system[j]); } } //Thread 4 ? for(i = 3*NO_OF_PARTICLES/4;i<NO_OF_PARTICLES;i++){ for(j = 0;j<NO_OF_PARTICLES;j++){ compute_interaction(&system[i],&system[j]); } } } __vector int get_quadrant_count(particle* system){ __vector int quad_count = VECINTZERO; __vector int quad_mask = VECINTZERO; int i; for(i = 0; i < NO_OF_PARTICLES ; i++){ __vector int top2 = (__vector int){1,1,0,0}; __vector int bottom2 = (__vector int){0,0,1,1}; __vector int left2 = (__vector int){0,1,0,1}; __vector int right2 = (__vector int){1,0,1,0}; __vector int mask1, mask2; __vector float vx = vec_splat(system[i].position,0); __vector float vy = vec_splat(system[i].position,1); mask1 = vec_sel(right2, left2, vec_cmpgt(vx,VECZERO)); mask2 = vec_sel(top2, bottom2, vec_cmpgt(vy,VECZERO)); quad_mask = vec_and(mask1,mask2); quad_count = vec_add(quad_count,quad_mask); } return quad_count; } void render(particle* system){ int i = 0; for(; i < NO_OF_PARTICLES; i++){ float *pos = (float*) &system[i].position; float *vel = (float*) &system[i].velocity; float *acc = (float*) &system[i].acceleration; printf("position : %f %f %f ", pos[0], pos[1], pos[2]); printf("velocity : %f %f %f ", vel[0], vel[1], vel[2]); printf("acceleration : %f %f %f \n", acc[0], acc[1], acc[2]); } } int main () { /* create particle system --> array of particles */ particle particle_system[NO_OF_PARTICLES] __attribute__((aligned(64))); /* vector that tracks the no. of particles in each quadrant */ __vector int quad_count; int * qc; /* place particles in 4 quadrants */ init_particles(particle_system); /* run simulation */ float simulationTime = 0.0; int iterations = COMPUTE_ITERATIONS; printf("----------------------------------------------"); printf("----------------------------------------------\n"); printf("Running Simulation with %d particles & %d iterations with %f seconds time steps\n", NO_OF_PARTICLES, COMPUTE_ITERATIONS, TIME_STEP); printf("----------------------------------------------"); printf("----------------------------------------------\n"); while(iterations > 0){ /* Compute */ update_particles(particle_system); /* Display */ //render(particle_system); /* Update Time */ simulationTime = simulationTime + TIME_STEP; printf("----------------------------------"); printf("Simulation Time: %f |",simulationTime); quad_count = get_quadrant_count(particle_system); qc = (int*)&quad_count; printf(" q1:%d q2:%d q3:%d q4:%d",qc[0], qc[1], qc[2], qc[3]); printf("----------------------------------\n"); iterations --; } return 0; }
// Main function int main(int argc, char** argv){ int myRank;// Rank of process int p;// Number of processes int n;// Number of total particles int previous;// Previous rank in the ring int next;// Next rank in the ring int tag = TAG;// Tag for message int number;// Number of local particles int count_mpi; struct Particle *globals;// Array of all particles in the system struct Particle *locals;// Array of local particles struct Particle *remotes;// Array of foreign particles char *file_name;// File name MPI_Status status;// Return status for receive int j, rounds, initiator, sender; double start_time, end_time; // checking the number of parameters if(argc < 2){ printf("ERROR: Not enough parameters\n"); printf("Usage: %s <number of particles> [<file>]\n", argv[0]); exit(1); } // getting number of particles n = atoi(argv[1]); // initializing MPI structures and checking p is odd MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myRank); MPI_Comm_size(MPI_COMM_WORLD, &p); if(p % 2 == 0){ p = p - 1; if(myRank == p){ MPI_Finalize(); return 0; } } srand(myRank+myRank*CONSTANT); // acquiring memory for particle arrays //**changed to make it right******* number = ceil(1.0 * n / p); locals = (struct Particle *) calloc(number , sizeof(struct Particle)); remotes = (struct Particle *) calloc(number , sizeof(struct Particle)); // checking for file information if(argc == 3){ if(myRank == 0){ globals = (struct Particle *) calloc((ceil((double)n/p))*p , sizeof(struct Particle)); // YOUR CODE GOES HERE (reading particles from file) read_file(globals, n, argv[2]); } // To send/recv (or scatter/gather) you will need to learn how to // transfer structs of floats, treat it as a contiguous block of // floats. Here is an example: // MPI_Send(locals, // number * (sizeof (struct Particle)) / sizeof(float), // MPI_FLOAT, // next_rank, // tag, // MPI_COMM_WORLD) // MPI_Recv(remotes, // number * (sizeof (struct Particle)) / sizeof(float), // MPI_FLOAT, // previous_rank, // tag, // MPI_COMM_WORLD, // &status); // hint: because your nodes need to both send and receive you // might consider asyncronous send/recv. // YOUR CODE GOES HERE (distributing particles among processors) count_mpi = number * (sizeof(struct Particle)) /sizeof(float); MPI_Scatter(globals, count_mpi, MPI_FLOAT, locals, count_mpi, MPI_FLOAT, 0, MPI_COMM_WORLD); } else { // random initialization of local particle array for(j = 0; j < number; j++){ locals[j].x = random_value(POSITION); locals[j].y = random_value(POSITION); locals[j].fx = 0.0; locals[j].fy = 0.0; locals[j].mass = MASS; } } // starting timer if(myRank == 0){ start_time = MPI_Wtime(); } // YOUR CODE GOES HERE (ring algorithm) MPI_Request request_send[4]; int nextRank = (myRank + 1) % p; int prevRank = (myRank - 1 + p) % p; MPI_Isend(locals, count_mpi, MPI_FLOAT, nextRank, tag, MPI_COMM_WORLD, &request_send[0]); MPI_Recv(remotes, count_mpi, MPI_FLOAT, prevRank, tag, MPI_COMM_WORLD, &status); compute_interaction(locals, remotes, number); MPI_Isend(remotes, count_mpi, MPI_FLOAT, nextRank, tag, MPI_COMM_WORLD, &request_send[1]); for(int i=1; i<(p-1)/2; i++){ MPI_Recv(remotes, count_mpi, MPI_FLOAT, prevRank, tag, MPI_COMM_WORLD, &status); compute_interaction(locals, remotes, number); MPI_Isend(remotes, count_mpi, MPI_FLOAT, nextRank, tag, MPI_COMM_WORLD, &request_send[2]); } int OG_rank = ((myRank - (p-1)/2 + p) % p); //maybe call get_OG_rank function here and not sure where to increment rank_count int final_rank = ((myRank + (p-1)/2 + p) % p); //send remote back to original process MPI_Isend(remotes, count_mpi, MPI_FLOAT, OG_rank, tag, MPI_COMM_WORLD, &request_send[3]); MPI_Recv(remotes, count_mpi, MPI_FLOAT, final_rank, tag, MPI_COMM_WORLD, &status); merge(locals, remotes, number); compute_self_interaction(locals, number); //not sure about second parameter ****** //Step 8 of algo MPI_Barrier(MPI_COMM_WORLD); //*********************************double check this**** // stopping timer if(myRank == 0){ end_time = MPI_Wtime(); printf("Duration: %f seconds\n", (end_time-start_time)); } // printing information on particles if(argc == 3){ // YOUR CODE GOES HERE (collect particles at rank 0) count_mpi = number * (sizeof(struct Particle)) /sizeof(float); MPI_Gather(locals, count_mpi, MPI_FLOAT, globals, count_mpi, MPI_FLOAT, 0, MPI_COMM_WORLD); if(myRank == 0) { print_particles(globals,n); } } // finalizing MPI structures MPI_Finalize(); }