arma::vec ERIscreen::forceJK(const arma::mat & Pa, const arma::mat & Pb, double tol, double kfrac) const { #ifdef _OPENMP int nth=omp_get_max_threads(); #else int nth=1; #endif // Get workers std::vector< std::vector<ForceDigestor *> > p(nth); #ifdef _OPENMP #pragma omp parallel for #endif for(int i=0;i<nth;i++) { p[i].resize(3); p[i][0]=new JFDigestor(Pa+Pb); p[i][1]=new KFDigestor(Pa,kfrac,false); p[i][2]=new KFDigestor(Pb,kfrac,false); } // Do calculation arma::vec f=calculate_force(p,tol); // Free memory for(size_t i=0;i<p.size();i++) for(size_t j=0;j<p[i].size();j++) delete p[i][j]; return f; }
/* The second part of the Velocity verlet algorithm, updates velocity */ void integrator::verlet_integration_velocity(verlet_list particle) { verlet_list *current = particle.next; vector_3d tmp_force = vector_3d(0,0,0); while(current != NULL){ vector_3d r = particle.data->pos.diff(current->data->pos, x_dim, y_dim, z_dim); if(r*r < cutoff*cutoff){ /* Update velocity and acceleration of the particle */ tmp_force = calculate_force(particle.data, current->data); // std::cout << "Calculating force: " << tmp_force; particle.data->incr_next_acc(tmp_force/particle.data->mass); current->data->decr_next_acc(tmp_force/current->data->mass); } current = current->next; } particle.data->vel += 0.5*(particle.data->acc + particle.data->get_next_acc())*h; particle.data->update_acceleration(); }
int main(){ /////////////////// //Initialize data// /////////////////// time_t t; int i,j,k; int amount = 1000; // Amount of particles int timesteps = 1000; // Amount of timesteps int refresh = 10; // Amount of timesteps without updating neighbour list double rc = 2.5; // Cutoff radius double rv; // Neighborlist radius double rho = 0.5; // Density double m = 1; // Mass of particles double region = pow((amount*m)/rho,1./3.); // Sidelength of region double dt = 0.005; // Timestep double kB = 1; // Boltzmannconstant double g = 0; // Guiding factor double T = 1; // Temperature double sigma = sqrt((2*kB*T*g)/m); // Whitenoise factor double sig = sqrt((kB*T)/m); // Initial velocity factor double vmax; // Maximum velocity of particles double kinetic; // Kinetic energy double positions[amount][3]; // Particle positions double velocities[amount][3]; // Particle velocities double forces[amount][3]; // Particle forces double amount_neighbors[amount]; // Amount of neighbors per particle double ****neighbor; // Neighbor List double *vel_sum; // For checking momentum conservation XiEta rnd_XiEta[amount][3]; // Array of linear independent normally distributed numbers srand((unsigned) time(&t)); // Set seed for random number generator /////////////////////////// //Setup initial positions// /////////////////////////// create_particles(positions, amount, region); initial_velocities(velocities, sig, m, amount); /////////////////////////////// //Allocate memory on the heap// /////////////////////////////// neighbor = malloc(amount*sizeof(double ***)); if (neighbor){ for (i=0; i<amount; ++i){ neighbor[i] = malloc(amount*sizeof(double **)); if (neighbor[i]){ for (j=0; j<amount; ++j){ neighbor[i][j] = malloc(3*sizeof(double *)); if (!neighbor[i][j]){ printf("\nMemory allocation error!\n"); } } } } } ////////////////// //Main algorithm// ////////////////// printf("timestep\tsum velocity\tkinetic energy per particle\n"); for (i=0; i<timesteps; i++){ if (i%refresh==0){ vmax = sqrt(max_abs(velocities, amount)); rv = rc + refresh*vmax*dt; update_neighborlist(neighbor, amount_neighbors, positions, rv, amount, region); } for (j=0; j<amount; j++){ for (k=0; k<3; k++){ rnd_XiEta[j][k] = normal_value(0,1); } } calculate_force(forces, neighbor, positions, region, amount); update_velocity(velocities, forces, dt, g, sigma, m, rnd_XiEta, amount); update_position(positions, velocities, dt, sigma, rnd_XiEta, amount); calculate_force(forces, neighbor, positions, region, amount); update_velocity(velocities, forces, dt, g, sigma, m, rnd_XiEta, amount); if (i%100==0){ vel_sum = sum_vel(velocities, amount); kinetic = kinetic_energy(velocities, m, amount); printf("%d\t\t%f\t%f\n", i, vel_sum[0]+vel_sum[1]+vel_sum[2], kinetic/amount); } } //////////////////////////// //Clear memory on the heap// //////////////////////////// for (i=0; i<amount; i++){ for (j=0; j<amount; j++){ free(neighbor[i][j]); } free(neighbor[i]); } free(neighbor); return 0; }