int main(int argc, char **argv) { const char* method = "mmm1d"; const char* datafile = "../inp_data/mmm/mmm1d_wall.dat"; MPI_Comm comm = MPI_COMM_WORLD; fcs_int comm_rank, comm_size; MPI_Init(&argc, &argv); MPI_Comm_size(comm, &comm_size); MPI_Comm_rank(comm, &comm_rank); fcs_int periodicity[3] = { 0, 0, 1 }; fcs_int node_grid[3] = {1, 1, comm_size}; fcs_int node[3]; if (comm_rank == 0) fprintf(stderr, "Creating cartesian communicator...\n"); MPI_Dims_create(comm_size, 3, node_grid); MPI_Cart_create(MPI_COMM_WORLD, 3, node_grid, periodicity, 1, &comm); if (comm_rank == 0) fprintf(stderr, " node_grid=(%d, %d, %d)\n", node_grid[0], node_grid[1], node_grid[2]); MPI_Cart_coords(comm, comm_rank, 3, node); fcs_int pid; if (comm_rank == 0) { printf("------------------------------\n"); printf("Running mmm1d test on %d nodes\n", comm_size); printf("------------------------------\n"); } fcs_float box_l[3] = { 10.0, 10.0, 10.0 }; fcs_float offset[3] = {0.0, 0.0, 0.0}; fcs_int n_particles=0, total_particles = 4; fcs_float charges[total_particles]; fcs_float positions[3*total_particles]; fcs_float forces[3*total_particles]; fcs_float potentials[total_particles]; fcs_float charge_sum = 0.0; if (comm_rank == 0) { printf("Reading %s...\n", datafile); FILE *data = fopen(datafile, "r"); if (!data) { fprintf(stderr, "ERROR: Can't read %s!\n", datafile); perror("ERROR"); exit(1); } for (pid = 0; pid < total_particles; pid++) { fscanf(data, "%lf %lf %lf", &positions[3*pid], &positions[3*pid+1], &positions[3*pid+2]); fscanf(data, "%lf", &charges[pid]); printf("read: %d %le %le %le %le\n", pid, charges[pid], positions[3*pid], positions[3*pid+1], positions[3*pid+2]); charge_sum += charges[pid]; } fclose(data); n_particles=total_particles; /* printf("Charge 1 with value %e, position %e %e %e\n",charges[0],positions[0],positions[1],positions[2]); printf("Charge %d with value %e, position %e %e %e\n", n_particles,charges[n_particles-1],positions[3*n_particles-3],positions[3*n_particles-2],positions[3*n_particles-1]); */ } else n_particles=0; FCS handle = NULL; FCSResult result = NULL; if (comm_rank == 0) printf("\nInitializing mmm1d...\n"); result = fcs_init(&handle, method, comm); assert_fcs(result); if (comm_rank == 0) printf("\nSetting 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, total_particles); if (result != NULL) { fcs_result_print_result(result); MPI_Finalize(); exit(1); } assert_fcs(result); /* Tuning */ if (comm_rank == 0) printf("\nTesting parameters interface...\n"); fcs_float val; fcs_int vali; fcs_mmm1d_get_far_switch_radius(handle, &val); if (comm_rank == 0) printf("default far switch radius: %f\n",val); fcs_mmm1d_set_far_switch_radius(handle, 6.0); fcs_mmm1d_get_far_switch_radius(handle, &val); if (comm_rank == 0) printf("new far switch radius: %f\n",val); fcs_mmm1d_get_bessel_cutoff(handle, &vali); if (comm_rank == 0) printf("default bessel_cutoff: %d\n",vali); fcs_mmm1d_set_bessel_cutoff(handle, 3); fcs_mmm1d_get_bessel_cutoff(handle, &vali); if (comm_rank == 0) printf("new bessel_cutoff: %d\n",vali); fcs_mmm1d_get_maxPWerror(handle, &val); if (comm_rank == 0) printf("default maxPWerror: %f\n",val); fcs_mmm1d_set_maxPWerror(handle, 0.0001); fcs_mmm1d_get_maxPWerror(handle, &val); if (comm_rank == 0) printf("new maxPWerror: %f\n",val); if (comm_rank == 0) printf("\nTesting tuning routine...\n"); result = fcs_tune(handle, n_particles, positions, charges); if (result != NULL) { fcs_result_print_result(result); MPI_Finalize(); exit(1); } //fcs_mmm1d_get_bessel_cutoff(handle, &vali); //printf("calculated bessel cutoff: %d\n",vali); if (comm_rank == 0) printf("\nTesting running routine...\n"); result = fcs_run(handle, n_particles, positions, charges, forces, potentials); assert_fcs(result); MPI_Barrier(comm); if (comm_rank == 0) { for(pid=0; pid<total_particles; pid++) { printf("Potential on particle %d: %e\n", pid, potentials[pid]); //printf("Potential on particle 2: %e\n", potentials[1]); printf("Force on particle %d: %e, %e, %e\n", pid, forces[3*pid], forces[3*pid+1], forces[3*pid+2]); //printf("Force on particle 2: %e, %e, %e\n", forces[3], forces[4], forces[5]); } printf("\nFinalizing...\n"); } fcs_destroy(handle); MPI_Finalize(); if (comm_rank == 0) printf("Done.\n"); return 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; }
int main(int argc, char* argv[]) { MPI_Comm comm; int comm_size, comm_rank; fcs_float *x, *q, *f, *p; fcs_int n_axis, n_total, n_local, n_local_max; fcs_int i, j, k; fcs_int p_c; FCS fcs_handle; FCSResult fcs_result; char method[] = "vmg"; fcs_float box_a[] = { 1.0, 0.0, 0.0 }; fcs_float box_b[] = { 0.0, 1.0, 0.0 }; fcs_float box_c[] = { 0.0, 0.0, 1.0 }; fcs_float offset[] = { 0.0, 0.0, 0.0 }; fcs_int periodic[] = { 0, 0, 0 }; fcs_int max_level = 6; fcs_int max_iterations = 20; fcs_int smoothing_steps = 3; fcs_int cycle_type = 1; fcs_float precision = 1e-10; fcs_int near_field_cells = 6; fcs_int interpolation_degree = 4; fcs_int discretization_order = 2; MPI_Init(&argc, &argv); comm = MPI_COMM_WORLD; MPI_Comm_size(comm, &comm_size); MPI_Comm_rank(comm, &comm_rank); n_axis = 16; n_total = n_axis * n_axis * n_axis; if (comm_rank == 0) { n_local = n_total; n_local_max = n_total; }else { n_local = 0; n_local_max = 0; } if (comm_rank == 0) { printf("*** RUNNING vmg TEST ***\n"); printf(" n_total = %" FCS_LMOD_INT "d\n", n_total); printf(" n_procs = %d\n", comm_size); printf(" periodicity_x = %d\n", periodic[0]); printf(" periodicity_y = %d\n", periodic[1]); printf(" periodicity_z = %d\n", periodic[2]); printf(" max_level = %d\n", max_level); printf(" max_iterations = %d\n", max_iterations); printf(" smoothing_steps = %d\n", smoothing_steps); printf(" cycle_type = %d\n", cycle_type); printf(" precision = %e\n", precision); printf(" near_field_cells = %d\n", near_field_cells); printf(" interpolation_degree = %d\n", interpolation_degree); printf(" discretization_order = %d\n", discretization_order); } x = (fcs_float*)malloc(3 * n_local_max * sizeof(fcs_float)); q = (fcs_float*)malloc(n_local_max * sizeof(fcs_float)); f = (fcs_float*)malloc(3 * n_local_max * sizeof(fcs_float)); p = (fcs_float*)malloc(n_local_max * sizeof(fcs_float)); if (comm_rank == 0) { p_c = 0; for (i=0; i<n_axis; ++i) for (j=0; j<n_axis; ++j) for (k=0; k<n_axis; ++k) { x[3*p_c ] = offset[0] + (i * box_a[0]) / n_axis; x[3*p_c+1] = offset[1] + (j * box_b[1]) / n_axis; x[3*p_c+2] = offset[2] + (k * box_c[2]) / n_axis; q[p_c] = ((i+j+k)%2 ? 1.0 : -1.0); ++p_c; } } fcs_result = fcs_init(&fcs_handle, method, comm); assert_fcs(fcs_result); fcs_result = fcs_set_common(fcs_handle, 1, box_a, box_b, box_c, offset, periodic, n_total); assert_fcs(fcs_result); fcs_result = fcs_vmg_setup(fcs_handle, max_level, max_iterations, smoothing_steps, cycle_type, precision, near_field_cells, interpolation_degree, discretization_order); assert_fcs(fcs_result); fcs_result = fcs_tune(fcs_handle, n_local, n_local_max, x, q); assert_fcs(fcs_result); fcs_result = fcs_run(fcs_handle, n_local, n_local_max, x, q, f, p); assert_fcs(fcs_result); fcs_destroy(fcs_handle); free(x); free(q); free(f); free(p); if (comm_rank == 0) printf("*** vmg DONE ***\n"); MPI_Finalize(); return 0; }
int main(int argc, char* argv[]) { MPI_Comm comm; int comm_size, comm_rank; fcs_float *x, *q, *f, *p; fcs_int n_axis, n_total, n_local, n_local_max; fcs_int i, j, k; fcs_int p_c, p_start, p_stop,ip; fcs_float e_local, e_total; fcs_float madelung_approx; const fcs_float madelung = 1.74756459463318219; int mpi_thread_requested = MPI_THREAD_MULTIPLE; int mpi_thread_provided; FCS fcs_handle; FCSResult fcs_result; char method[] = "pepc"; fcs_float box_a[] = { 1.0, 0.0, 0.0 }; fcs_float box_b[] = { 0.0, 1.0, 0.0 }; fcs_float box_c[] = { 0.0, 0.0, 1.0 }; fcs_float offset[] = { 0.0, 0.0, 0.0 }; fcs_int periodic[] = { 1, 1, 1 }; //fcs_int periodic[] = { 0, 0, 0 }; fcs_float theta = 0.2; fcs_float epsilon = 1.23e-6; MPI_Init_thread(&argc, &argv, mpi_thread_requested, &mpi_thread_provided); comm = MPI_COMM_WORLD; MPI_Comm_size(comm, &comm_size); MPI_Comm_rank(comm, &comm_rank); if (mpi_thread_provided < mpi_thread_requested && comm_rank == 0) { printf("Call to MPI_INIT_THREAD failed. Requested/provided level of multithreading: %d / %d. Continuing but expect program crash.\n", mpi_thread_requested, mpi_thread_provided); } n_axis = 16; n_total = n_axis * n_axis * n_axis; n_local = n_total / comm_size; if(comm_rank == comm_size-1) n_local += n_total % comm_size; n_local_max = n_total / comm_size + n_total % comm_size; if (comm_rank == 0) { printf("*** RUNNING pepc TEST ***\n"); printf(" n_total = %" FCS_LMOD_INT "d\n", n_total); printf(" n_procs = %d\n", comm_size); printf(" theta = %e\n", theta); printf(" epsilon = %e\n", epsilon); } x = (fcs_float*)malloc(3 * n_local * sizeof(fcs_float)); q = (fcs_float*)malloc( n_local * sizeof(fcs_float)); f = (fcs_float*)malloc(3 * n_local * sizeof(fcs_float)); p = (fcs_float*)malloc( n_local * sizeof(fcs_float)); p_c = 0; p_start = comm_rank*(n_total/comm_size); p_stop = p_start + n_local; for (ip=p_start; ip<p_stop; ip++, p_c++) { i = ip % n_axis; j = (ip / n_axis) % n_axis; k = ip / (n_axis*n_axis); x[3*p_c ] = offset[0] + (i * box_a[0]) / n_axis; x[3*p_c+1] = offset[1] + (j * box_b[1]) / n_axis; x[3*p_c+2] = offset[2] + (k * box_c[2]) / n_axis; q[p_c] = ((i+j+k)%2 ? 1.0 : -1.0); /* printf("init positions (rank %d) for particle id %d: %e %e %e %e\n", */ /* comm_rank, ip, x[3*p_c ], x[3*p_c+1], x[3*p_c+2], q[p_c]); */ } fcs_result = fcs_init(&fcs_handle, method, comm); assert_fcs(fcs_result); fcs_result = fcs_set_common(fcs_handle, 1, box_a, box_b, box_c, offset, periodic, n_total); assert_fcs(fcs_result); fcs_result = fcs_pepc_setup(fcs_handle, epsilon, theta); assert_fcs(fcs_result); fcs_result = fcs_tune(fcs_handle, n_local, n_local_max, x, q); assert_fcs(fcs_result); fcs_result = fcs_run(fcs_handle, n_local, n_local_max, x, q, f, p); assert_fcs(fcs_result); e_local = 0.0; for (i=0; i<n_local; ++i) e_local += p[i] * q[i]; MPI_Reduce(&e_local, &e_total, 1, MPI_DOUBLE, MPI_SUM, 0, comm); //madelung_approx = 8.0 * M_PI / n_axis * e_total / n_total; madelung_approx = 1.0 / n_axis * e_total / n_total; if (comm_rank == 0) { printf("\n"); printf(" Results:\n"); printf(" Energy: %e\n", e_total); printf(" Madelung constant: %e\n", madelung_approx); printf(" Relative error: %e\n", fabs(madelung-fabs(madelung_approx))/madelung); } p_c = 0; p_start = comm_rank*(n_total/comm_size); p_stop = p_start + n_local; for (ip=p_start; ip<p_stop; ip++, p_c++) { /* printf("results (rank %d) for particle id %d: %e %e %e %e\n", */ /* comm_rank, ip, f[3*p_c ], f[3*p_c+1], f[3*p_c+2], p[p_c]); */ /* printf("dataout: %e %e %e %e %e %e %e %e\n", x[3*p_c ], x[3*p_c+1], x[3*p_c+2], q[p_c], */ /* f[3*p_c ], f[3*p_c+1], f[3*p_c+2], p[p_c]); */ } fcs_destroy(fcs_handle); free(x); free(q); free(f); free(p); if (comm_rank == 0) printf("*** pepc DONE ***\n"); MPI_Finalize(); 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; }