void calculate_force(double forces[][3], double ****neighbor, double particles[][3], double region, int amount){ // Updates the force for each particle based on the neighbor list int i,j,k; double r = region/2.; for (i=0; i<amount; i++){ for (j=0; j<3; j++){ forces[i][j] = 0; } } omp_set_num_threads(NUM_THREADS); #pragma omp parallel for private(j,k) for (i=0; i<amount; i++){ int neighbors = *neighbor[i][0][0]; for (j=1; j<=neighbors; j++){ double d = distance_periodic(particles[i],*neighbor[i][j],region); double di = 1./d; double d3 = di * di *di; for (k=0; k<3; k++){ double dl = particles[i][k] - *neighbor[i][j][k]; if (dl > r){ dl -= region; } else if (dl < -r){ dl += region; } forces[i][k] += 48.*d3*(d3-0.5)*di*dl; } } } #pragma omp barrier }
void update_neighborlist(double ****neighbor, double *amount_neighbor, double particles[][3], double radius, int amount, double region){ // Updates the neighbor list for each particle within a given radius // The first element of each row contains a pointer to the amount of neighbors int i,j,k; omp_set_num_threads(NUM_THREADS); #pragma omp parallel for private(j,k) for (i=0; i<amount; i++){ int l = 0; for (j=0; j<amount; j++){ if (i!=j){ double distance_ij = distance_periodic(particles[i],particles[j],region); if (distance_ij<radius*radius){ for (k=0; k<3; k++){ neighbor[i][l+1][k] = &particles[j][k]; } l++; } } } amount_neighbor[i] = (double)l; neighbor[i][0][0] = &amount_neighbor[i]; } #pragma omp barrier }
void test_distance_periodic(void) { //real distance_periodic(Vector p1, Vector p2) real L = 32; Vector a, b; a.x = 1; a.y = 1; b.x = 31; b.y = 1; assert_almost_equal(distance_periodic(a, b, L), real(2)); a.x = 1; a.y = 1; b.x = 1; b.y = 31; assert_almost_equal(distance_periodic(a, b, L), real(2)); a.x = 1; a.y = 1; b.x = 31; b.y = 31; assert_almost_equal(distance_periodic(a, b, L), real(2)*std::sqrt(real(2))); a.x = 1; a.y = 1; b.x = 3; b.y = 1; assert_almost_equal(distance_periodic(a, b, L), real(2)); a.x = 1; a.y = 1; b.x = 1; b.y = 3; assert_almost_equal(distance_periodic(a, b, L), real(2)); a.x = 1; a.y = 1; b.x = 3; b.y = 3; assert_almost_equal(distance_periodic(a, b, L), real(2)*std::sqrt(real(2))); }