Esempio n. 1
0
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;
}