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 }
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; }
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; }