Esempio n. 1
0
void unpack_fcs(void) {

  fcs_float vir[9] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
  FCSResult result;
  real pot1, pot2, e, c, sum=0.0, fac=0.5;
  int n, m, k, i;

  /* extract output and distribute it to cell array */
  n=0; m=0; pot1=0.0;
  for (k=0; k<NCELLS; ++k) {
    cell *p = CELLPTR(k);
    for (i=0; i<p->n; ++i) { 
      c = CHARGE(p,i) * coul_eng;
      KRAFT(p,i,X) += field[n++] * c; 
      KRAFT(p,i,Y) += field[n++] * c; 
      KRAFT(p,i,Z) += field[n++] * c;
      e = pot[m++] * c * fac;
      POTENG(p,i)  += e;
      pot1         += e;
    }
  }

  /* unpack virial */
  result = fcs_get_virial(handle, vir);
  ASSERT_FCS(result);
#ifdef P_AXIAL
  vir_xx += vir[0];
  vir_yy += vir[4];
  vir_zz += vir[8];
#else
  virial += vir[0] + vir[4] + vir[8];
#endif
#ifdef STRESS_TENS
  if (do_press_calc) {
    /* distribute virial tensor evenly on all atoms */
    sym_tensor pp;
    pp.xx = vir[0] / natoms;
    pp.yy = vir[4] / natoms;
    pp.zz = vir[8] / natoms;
    pp.yz = (vir[5]+vir[7]) / (2*natoms);
    pp.zx = (vir[2]+vir[6]) / (2*natoms);
    pp.xy = (vir[1]+vir[3]) / (2*natoms);
    for (k=0; k<NCELLS; ++k) {
      cell *p = CELLPTR(k);
      for (i=0; i<p->n; ++i) { 
        PRESSTENS(p,i,xx) += pp.xx;
        PRESSTENS(p,i,yy) += pp.yy;
        PRESSTENS(p,i,zz) += pp.zz;
        PRESSTENS(p,i,yz) += pp.yz;
        PRESSTENS(p,i,zx) += pp.zx;
        PRESSTENS(p,i,xy) += pp.xy;
      }
    }
  }
#endif

  /* sum up potential energy */
#ifdef MPI
  MPI_Allreduce( &pot1, &pot2, 1, MPI_DOUBLE, MPI_SUM, cpugrid);
  tot_pot_energy += pot2;
#else
  tot_pot_energy += pot1;
#endif
}
Esempio n. 2
0
int main(int argc, char **argv)
{
  int comm_rank, comm_size;
  const char* method = "p2nfft";
/* DEBUG */  
//  const char* datafile = "../inp_data/p2nfft/debug_wall_small.dat";
  const char* datafile = "../inp_data/p3m/p3m_wall.dat";
  MPI_Comm comm = MPI_COMM_WORLD;
  fcs_int periodicity[3] = { 1, 1, 1 };
  fcs_int pid;
  fcs_float tolerance = 1.e-3;

  MPI_Init(&argc, &argv);

  MPI_Comm_size(comm, &comm_size);
  MPI_Comm_rank(comm, &comm_rank);

  if(!comm_rank){
    printf("-------------------\n");
    printf("Running p2nfft test\n");
    printf("-------------------\n");
  }

  fcs_float box_l[3] = { 10.0, 10.0, 10.0 };
  fcs_float offset[3] = {0.0, 0.0, 0.0};
/* DEBUG */  
//  int n_particles = 4;
  int n_particles = 300;

  fcs_float charges[300];
  fcs_float positions[900];
  fcs_float far_fields[900];
  fcs_float forces[900];
  fcs_float reference_forces[900];
  fcs_float far_potentials[300];
  fcs_float energies[300];
  fcs_float virial[9];

  fcs_int local_particles = 0;
  fcs_float local_charges[300];
  fcs_float local_positions[900];
  fcs_int global_particle_indices[300];


  if(!comm_rank)
    printf("Reading %s...\n", datafile);
  FILE *data = fopen(datafile, "r");
  if (!data) {
    fprintf(stderr, "ERROR: Can't read %s!", datafile);
    perror("ERROR");
    exit(1);
  }
  
  fcs_float charge_sum = 0.0;
  for (pid = 0; pid < n_particles; pid++) {
    fscanf(data, "%" FCS_CONV_FLOAT "f %" FCS_CONV_FLOAT "f %" FCS_CONV_FLOAT "f",
        &positions[3*pid], &positions[3*pid+1], &positions[3*pid+2]);
    fscanf(data, "%" FCS_CONV_FLOAT "f",
        &charges[pid]);
    fscanf(data, "%" FCS_CONV_FLOAT "f %" FCS_CONV_FLOAT "f %" FCS_CONV_FLOAT "f",
        &reference_forces[3*pid], &reference_forces[3*pid+1], &reference_forces[3*pid+2]);
    charge_sum += charges[pid];
  }

  fclose(data);


  FCS handle = NULL;
  FCSResult result = NULL;

  MPI_Barrier(MPI_COMM_WORLD);
  if(!comm_rank)
    printf("Initializing p2nfft...\n");
  result = fcs_init(&handle, method, comm);
  assert_fcs(result);

  if(!comm_rank)
    printf("Reading particles ... \n");
  for (pid = 0; pid < n_particles; ++pid) {
    if (pid % comm_size == comm_rank) {
      local_charges[local_particles] = charges[pid];
      local_positions[3*local_particles] = positions[3*pid];
      local_positions[3*local_particles+1] = positions[3*pid+1];
      local_positions[3*local_particles+2] = positions[3*pid+2];
      global_particle_indices[local_particles] = pid;
      ++local_particles;
    }
  }

  if(!comm_rank)
    printf("Setting parameters...\n");

  fcs_float box_a[3] = { 0.0, 0.0, 0.0 };
  fcs_float box_b[3] = { 0.0, 0.0, 0.0 };
  fcs_float box_c[3] = { 0.0, 0.0, 0.0 };
  box_a[0] = box_l[0];
  box_b[1] = box_l[1];
  box_c[2] = box_l[2];

  result = fcs_set_common(handle, 1, box_a, box_b, box_c,
     offset, periodicity, n_particles);
  assert_fcs(result);

  /* Tuning */
  fcs_set_tolerance(handle, FCS_TOLERANCE_TYPE_FIELD, tolerance);

  if(!comm_rank)
    printf("Tuning p2nfft to tolerance %" FCS_LMOD_FLOAT "e...\n", tolerance);
  result = fcs_tune(handle, local_particles, local_positions, local_charges);
  assert_fcs(result);

  /* activate virial computation */
  result = fcs_set_compute_virial(handle, 1);
  assert_fcs(result);

  /* Far field computation */
  if(!comm_rank)
    printf("Running p2nfft (computing far fields and potentials)...\n");
  result = fcs_run(handle, local_particles,
      local_positions, local_charges, far_fields, far_potentials);
  assert_fcs(result);

  /* get and print virial */
  result = fcs_get_virial(handle, virial);
  assert_fcs(result);

  if(!comm_rank)
    printf("virial tensor = [%" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e; %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e; %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e]\n", virial[0], virial[1], virial[2],
        virial[3], virial[4], virial[5], virial[6], virial[7], virial[8]);

  /* Add components */
  for (pid = 0; pid < local_particles; pid++) {
    forces[3*pid]   = local_charges[pid] * far_fields[3*pid];
    forces[3*pid+1] = local_charges[pid] * far_fields[3*pid+1];
    forces[3*pid+2] = local_charges[pid] * far_fields[3*pid+2];

    energies[pid] = 0.5 * local_charges[pid] * far_potentials[pid];
  }
  
  /* Compare forces to reference field */
  fcs_float sqr_sum = 0.0;
  fcs_float sum_energy = 0.0;
  for (pid = 0; pid < local_particles; pid++) {
    sum_energy += energies[pid];

    fcs_float d0 = forces[3*pid]   - reference_forces[3*global_particle_indices[pid]];
    fcs_float d1 = forces[3*pid+1] - reference_forces[3*global_particle_indices[pid]+1];
    fcs_float d2 = forces[3*pid+2] - reference_forces[3*global_particle_indices[pid]+2];
    sqr_sum += d0*d0+d1*d1+d2*d2;
  }

  /* Reduce to global values */
  fcs_float global_total_energy, global_sqr_sum;
  MPI_Reduce(&sum_energy, &global_total_energy, 1, FCS_MPI_FLOAT, MPI_SUM, 0, MPI_COMM_WORLD);
  MPI_Reduce(&sqr_sum, &global_sqr_sum, 1, FCS_MPI_FLOAT, MPI_SUM, 0, MPI_COMM_WORLD);
  if (!comm_rank) {
    printf("sum_energy=%" FCS_LMOD_FLOAT "f\n", global_total_energy);
    printf("rms_error=%e\n", sqrt(global_sqr_sum / (fcs_float)n_particles));
  }

  if(!comm_rank)
    printf("Finalizing...\n");
  fcs_destroy(handle);

  MPI_Finalize();
  if(!comm_rank)
    printf("Done.\n");

  return 0;
}
Esempio n. 3
0
int main(int argc, char **argv)
{
  fcs_int total_num_particles = TEST_N_PARTICLES;
  fcs_int num_particles, max_num_particles;
  fcs_float box_size = TEST_BOX_SIZE;
  fcs_int pid, px, py, pz;
  fcs_float positions[3*TEST_N_PARTICLES];
  fcs_float charges[TEST_N_PARTICLES];
  fcs_float direct_fields[3*TEST_N_PARTICLES];
  fcs_float direct_potentials[TEST_N_PARTICLES];
  fcs_float p2nfft_fields[3*TEST_N_PARTICLES];
  fcs_float p2nfft_potentials[TEST_N_PARTICLES];
  fcs_float direct_virial[9], p2nfft_virial[9];
  
  MPI_Init(&argc, &argv);
  MPI_Comm comm = MPI_COMM_WORLD;
  int comm_rank, comm_size;
  MPI_Comm_size(comm, &comm_size);
  MPI_Comm_rank(comm, &comm_rank);

  pid = num_particles = 0;
  for (px = 0; px < TEST_BOX_SIZE; ++px) {
    for (py = 0; py < TEST_BOX_SIZE; ++py) {
      for (pz = 0; pz < TEST_BOX_SIZE; ++pz, ++pid) {
        if (pid % comm_size == comm_rank) {
          positions[3*num_particles] = px + 0.5;
          positions[3*num_particles + 1] = py + 0.5;
          positions[3*num_particles + 2] = pz + 0.5;
          charges[num_particles] = 1.0-((px + py + pz) % 2)*2;
          ++num_particles;
        }
      }
    }
  }
  max_num_particles = num_particles;

/* Debugging */
for(int t=0; t<6; t++)
  fprintf(stderr, "init positions[%d] = %" FCS_LMOD_FLOAT "f\n", t, positions[t]);

  fcs_float box_a[] = { box_size, 0.0, 0.0 };
  fcs_float box_b[] = { 0.0, box_size, 0.0 };
  fcs_float box_c[] = { 0.0, 0.0, box_size };
  fcs_float offset[] = {0.0, 0.0, 0.0};
  fcs_int periodicity[] = {0, 0, 0};
//  fcs_int periodicity[] = {1, 1, 1};

  FCS fcs_handle = NULL;
  FCSResult fcs_result = NULL;

  /* Calculate this system via FCS direct solver */
  fcs_result = fcs_init(&fcs_handle, "direct", comm);
  assert_fcs(fcs_result);

  fcs_result = fcs_set_common(fcs_handle, 1, box_a, box_b, box_c, offset, periodicity, total_num_particles);
  assert_fcs(fcs_result);

  fcs_result = fcs_set_max_local_particles(fcs_handle, max_num_particles);
  assert_fcs(fcs_result);

  fcs_result = fcs_tune(fcs_handle, num_particles, positions, charges);
  assert_fcs(fcs_result);

  fcs_result = fcs_set_compute_virial(fcs_handle, 1);
  assert_fcs(fcs_result);

/* Debugging */
for(int t=0; t<6; t++)
  fprintf(stderr, "before direct run: positions[%d] = %" FCS_LMOD_FLOAT "f\n", t, positions[t]);

  fcs_result = fcs_run(fcs_handle, num_particles, positions, charges,
      direct_fields, direct_potentials);
  assert_fcs(fcs_result);

/* Debugging */
for(int t=0; t<6; t++)
  fprintf(stderr, "after direct run: positions[%d] = %" FCS_LMOD_FLOAT "f\n", t, positions[t]);

  fcs_result = fcs_get_virial(fcs_handle, direct_virial);
  assert_fcs(fcs_result);

  printf("Virial via FCS direct:\n");
  if(!comm_rank)
    printf("virial tensor = [%" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e; %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e; %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e]\n", direct_virial[0], direct_virial[1], direct_virial[2],
        direct_virial[3], direct_virial[4], direct_virial[5], direct_virial[6], direct_virial[7], direct_virial[8]);

  printf("Potentials via FCS direct:\n");
  for (pid = 0; pid < num_particles; ++pid)
    printf("%" FCS_LMOD_FLOAT "f\n", direct_potentials[pid]);

  printf("Fields via FCS direct:\n");
  for (pid = 0; pid < num_particles; ++pid)
    printf("[%" FCS_LMOD_FLOAT "f %" FCS_LMOD_FLOAT "f %" FCS_LMOD_FLOAT "f]\n", direct_fields[3*pid+0], direct_fields[3*pid+1], direct_fields[3*pid+2]);

  fcs_destroy(fcs_handle);


  /* set p2nfft specific parameters */
  fcs_float tolerance = 1.e-3;
  
  /* Calculate this system via FCS p2nfft solver */
  fcs_result = fcs_init(&fcs_handle, "p2nfft", comm);
  assert_fcs(fcs_result);

  fcs_result = fcs_set_common(fcs_handle, 1, box_a, box_b, box_c, offset, periodicity, total_num_particles);
  assert_fcs(fcs_result);

  fcs_result = fcs_set_max_local_particles(fcs_handle, max_num_particles);
  assert_fcs(fcs_result);

  fcs_set_tolerance(fcs_handle, FCS_TOLERANCE_TYPE_POTENTIAL, tolerance);
  fcs_result = fcs_tune(fcs_handle, num_particles, positions, charges);
  assert_fcs(fcs_result);

  fcs_result = fcs_set_compute_virial(fcs_handle, 1);
  assert_fcs(fcs_result);

/* Debugging */
for(int t=0; t<6; t++)
  fprintf(stderr, "test: positions[%d] = %" FCS_LMOD_FLOAT "f\n", t, positions[t]);

  fcs_result = fcs_run(fcs_handle, num_particles, positions, charges,
      p2nfft_fields, p2nfft_potentials);
  assert_fcs(fcs_result);

  fcs_result = fcs_get_virial(fcs_handle, p2nfft_virial);
  assert_fcs(fcs_result);

  printf("Virial via FCS p2nfft:\n");
  if(!comm_rank)
    printf("virial tensor = [%" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e; %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e; %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e %" FCS_LMOD_FLOAT "e]\n", p2nfft_virial[0], p2nfft_virial[1], p2nfft_virial[2],
        p2nfft_virial[3], p2nfft_virial[4], p2nfft_virial[5], p2nfft_virial[6], p2nfft_virial[7], p2nfft_virial[8]);

  printf("Potentials via FCS p2nfft:\n");
  for (pid = 0; pid < num_particles; ++pid)
    printf("%" FCS_LMOD_FLOAT "f\n", p2nfft_potentials[pid]);

  printf("Fields via FCS p2nfft:\n");
  for (pid = 0; pid < num_particles; ++pid)
    printf("[%" FCS_LMOD_FLOAT "f %" FCS_LMOD_FLOAT "f %" FCS_LMOD_FLOAT "f]\n", p2nfft_fields[3*pid+0], p2nfft_fields[3*pid+1], p2nfft_fields[3*pid+2]);

  fcs_destroy(fcs_handle);

  /* Compare results of direct and p2nfft solver */

  fcs_float direct_energy = 0, p2nfft_energy = 0;
  for (pid = 0; pid < num_particles; pid++) {
    direct_energy += 0.5 * charges[pid] * direct_potentials[pid];
    p2nfft_energy += 0.5 * charges[pid] * p2nfft_potentials[pid];
  }

  fcs_float sqr_sum = 0.0;
  for (pid = 0; pid < num_particles; ++pid) {
    fcs_float d0 = p2nfft_fields[3*pid]   - direct_fields[3*pid];
    fcs_float d1 = p2nfft_fields[3*pid+1] - direct_fields[3*pid+1];
    fcs_float d2 = p2nfft_fields[3*pid+2] - direct_fields[3*pid+2];
    sqr_sum += d0*d0+d1*d1+d2*d2;
  }

  /* Reduce to global values */
  fcs_float direct_total_energy, p2nfft_total_energy, total_sqr_sum;
  MPI_Reduce(&direct_energy, &direct_total_energy, 1, FCS_MPI_FLOAT, MPI_SUM, 0, MPI_COMM_WORLD);
  MPI_Reduce(&p2nfft_energy, &p2nfft_total_energy, 1, FCS_MPI_FLOAT, MPI_SUM, 0, MPI_COMM_WORLD);
  MPI_Reduce(&sqr_sum, &total_sqr_sum, 1, FCS_MPI_FLOAT, MPI_SUM, 0, MPI_COMM_WORLD);

  if (!comm_rank) {
    printf("direct_energy = %" FCS_LMOD_FLOAT "f\n", direct_total_energy);
    printf("p2nfft_energy = %" FCS_LMOD_FLOAT "f\n", p2nfft_total_energy);
    printf("rms_error = %e\n", sqrt(total_sqr_sum / (fcs_float)total_num_particles));
  }

  MPI_Finalize();

  return 0;
}