/* combined setter function for all fmm parameters */ FCSResult fcs_fmm_setup(FCS handle, fcs_int absrel, fcs_float tolerance_energy, fcs_int dipole_correction, fcs_int system, fcs_int maxdepth, fcs_int unroll_limit, fcs_int load/*, fcs_int potential, fcs_float radius*/) { FCSResult result; result = fcs_fmm_set_absrel(handle,absrel); CHECK_RESULT_RETURN(result); result = fcs_fmm_set_tolerance_energy(handle,tolerance_energy); CHECK_RESULT_RETURN(result); result = fcs_fmm_set_dipole_correction(handle, dipole_correction); CHECK_RESULT_RETURN(result); result = fcs_fmm_set_internal_tuning(handle, system); CHECK_RESULT_RETURN(result); result = fcs_fmm_set_maxdepth(handle, maxdepth); CHECK_RESULT_RETURN(result); result = fcs_fmm_set_unroll_limit(handle, unroll_limit); CHECK_RESULT_RETURN(result); result = fcs_fmm_set_balanceload(handle, load); CHECK_RESULT_RETURN(result); /* result = fcs_fmm_set_potential(handle, potential); CHECK_RESULT_RETURN(result); result = fcs_fmm_set_dipole_correction(handle, dipole_correction); CHECK_RESULT_RETURN(result); */ return FCS_RESULT_SUCCESS; }
/* initialization function for basic fmm parameters */ FCSResult fcs_fmm_init(FCS handle) { FMM_CHECK_RETURN_RESULT(handle, __func__); handle->fmm_param = malloc(sizeof(*handle->fmm_param)); /* setting fmm parameters to invalid values (or default values, if possible) */ handle->fmm_param->absrel = FCS_FMM_STANDARD_ERROR; handle->fmm_param->tolerance_energy = -1.0; handle->fmm_param->dipole_correction = -1; handle->fmm_param->potential = -1; handle->fmm_param->cusp_radius = -1.0; fcs_fmm_set_absrel( handle, FCS_FMM_CUSTOM_RELATIVE ); fcs_fmm_set_tolerance_energy( handle, 1e-3 ); fcs_fmm_set_dipole_correction( handle, FCS_FMM_ACTIVE_DIPOLE_CORRECTION ); fcs_fmm_set_internal_tuning( handle, FCS_FMM_HOMOGENOUS_SYSTEM ); fcs_fmm_set_balanceload( handle, 1 ); fcs_fmm_set_define_loadvector( handle, 1 ); fcs_fmm_set_maxdepth( handle, 20 ); fcs_fmm_set_unroll_limit( handle, 9 ); /* FCSResult result; */ void* ptr; ptr = malloc(4096); fmm_cinit(ptr); fcs_set_method_context( handle, ptr ); handle->fmm_param->wignersize = 0; handle->fmm_param->wignerptr = NULL; fcs_fmm_set_max_particle_move(handle, -1); fcs_fmm_set_resort(handle, 0); handle->fmm_param->fmm_resort = FCS_FMM_RESORT_NULL; handle->shift_positions = 0; handle->destroy = fcs_fmm_destroy; handle->set_tolerance = fcs_fmm_set_tolerance; /* handle->get_tolerance = fcs_fmm_get_tolerance;*/ handle->set_parameter = fcs_fmm_set_parameter; handle->print_parameters = fcs_fmm_print_parameters; handle->tune = fcs_fmm_tune; handle->run = fcs_fmm_run; handle->set_compute_virial = fcs_fmm_require_virial; handle->get_virial = fcs_fmm_get_virial; handle->set_max_particle_move = fcs_fmm_set_max_particle_move; handle->set_resort = fcs_fmm_set_resort; handle->get_resort = fcs_fmm_get_resort; handle->get_resort_availability = fcs_fmm_get_resort_availability; handle->get_resort_particles = fcs_fmm_get_resort_particles; handle->resort_ints = fcs_fmm_resort_ints; handle->resort_floats = fcs_fmm_resort_floats; handle->resort_bytes = fcs_fmm_resort_bytes; return FCS_RESULT_SUCCESS; }
FCSResult fcs_fmm_set_tolerance(FCS handle, fcs_int tolerance_type, fcs_float tolerance) { FMM_CHECK_RETURN_RESULT(handle, __func__); if (tolerance_type == FCS_TOLERANCE_TYPE_ENERGY) { fcs_fmm_set_absrel(handle, FCS_FMM_CUSTOM_ABSOLUTE); fcs_fmm_set_tolerance_energy(handle, tolerance); } else if (tolerance_type == FCS_TOLERANCE_TYPE_ENERGY_REL) { fcs_fmm_set_absrel(handle, FCS_FMM_CUSTOM_RELATIVE); fcs_fmm_set_tolerance_energy(handle, tolerance); } else { return fcs_result_create(FCS_ERROR_NULL_ARGUMENT, __func__, "Unsupported tolerance type. FMM only supports FCS_TOLERANCE_TYPE_ENERGY and FCS_TOLERANCE_TYPE_ENERGY_REL."); } return FCS_RESULT_SUCCESS; }
void init_fcs(void) { FCSResult res; fcs_int srf = 1; char *method; fcs_int pbc [3] = { pbc_dirs.x, pbc_dirs.y, pbc_dirs.z }; fcs_float BoxX[3] = { box_x.x, box_x.y, box_x.z }; fcs_float BoxY[3] = { box_y.x, box_y.y, box_y.z }; fcs_float BoxZ[3] = { box_z.x, box_z.y, box_z.z }; fcs_float off [3] = { 0.0, 0.0, 0.0 }; /* subtract CM momentum */ if (0 == imdrestart) { int i, k; real ptot[4], ptot_2[4], px, py, pz; ptot[0] = 0.0; ptot[1] = 0.0; ptot[2] = 0.0, ptot[3] = 0.0; for (k=0; k<NCELLS; ++k) { /* loop over all cells */ cell *p = CELLPTR(k); for (i=0; i<p->n; i++) { ptot[0] += IMPULS(p,i,X); ptot[1] += IMPULS(p,i,Y); ptot[2] += IMPULS(p,i,Z); ptot[3] += MASSE(p,i); } } #ifdef MPI MPI_Allreduce( ptot, ptot_2, 4, REAL, MPI_SUM, cpugrid); ptot[0] = ptot_2[0]; ptot[1] = ptot_2[1]; ptot[2] = ptot_2[2]; ptot[3] = ptot_2[3]; #endif px = ptot[0]/ptot[3]; py = ptot[1]/ptot[3]; pz = ptot[2]/ptot[3]; for (k=0; k<NCELLS; ++k) { /* loop over all cells */ cell *p = CELLPTR(k); for (i=0; i<p->n; i++) { IMPULS(p,i,X) -= px * MASSE(p,i); IMPULS(p,i,Y) -= py * MASSE(p,i); IMPULS(p,i,Z) -= pz * MASSE(p,i); } } } switch (fcs_method) { case FCS_METH_DIRECT: method = "direct"; break; case FCS_METH_PEPC: method = "pepc"; break; case FCS_METH_FMM: method = "fmm"; break; case FCS_METH_P3M: method = "p3m"; srf = fcs_near_field_flag; break; case FCS_METH_P2NFFT: method = "p2nfft"; srf = fcs_near_field_flag; break; case FCS_METH_VMG: method = "vmg"; break; case FCS_METH_PP3MG: method = "pp3mg"; break; } /* initialize handle and set common parameters */ res = fcs_init(&handle, method, cpugrid); ASSERT_FCS(res); res = fcs_set_common(handle, srf, BoxX, BoxY, BoxZ, off, pbc, natoms); ASSERT_FCS(res); res = fcs_require_virial(handle, 1); ASSERT_FCS(res); /* set method specific parameters */ switch (fcs_method) { #ifdef FCS_ENABLE_DIRECT case FCS_METH_DIRECT: /* nothing to do */ break; #endif #ifdef FCS_ENABLE_PEPC case FCS_METH_PEPC: res = fcs_pepc_setup(handle, (fcs_float)fcs_pepc_eps, (fcs_float)fcs_pepc_theta ); ASSERT_FCS(res); res = fcs_pepc_set_num_walk_threads( handle, (fcs_int)fcs_pepc_nthreads ); ASSERT_FCS(res); break; #endif #ifdef FCS_ENABLE_FMM case FCS_METH_FMM: res = fcs_fmm_set_absrel(handle, (fcs_int)fcs_fmm_absrel); ASSERT_FCS(res); res = fcs_fmm_set_tolerance_energy(handle, (fcs_float)fcs_tolerance); ASSERT_FCS(res); break; #endif #ifdef FCS_ENABLE_P3M case FCS_METH_P3M: if (0==srf) { res = fcs_p3m_set_r_cut(handle, (fcs_float)fcs_rcut); ASSERT_FCS(res); } res = fcs_set_tolerance(handle, FCS_TOLERANCE_TYPE_FIELD, (fcs_float)fcs_tolerance); ASSERT_FCS(res); if (fcs_grid_dim.x) res = fcs_p3m_set_grid(handle, (fcs_int)fcs_grid_dim.x); ASSERT_FCS(res); break; #endif #ifdef FCS_ENABLE_P2NFFT case FCS_METH_P2NFFT: if (0==srf) { res = fcs_p2nfft_set_r_cut(handle, (fcs_float)fcs_rcut); ASSERT_FCS(res); } res = fcs_set_tolerance(handle, FCS_TOLERANCE_TYPE_FIELD, (fcs_float)fcs_tolerance); ASSERT_FCS(res); if (fcs_grid_dim.x) { res = fcs_p2nfft_set_grid(handle, (fcs_int)fcs_grid_dim.x, (fcs_int)fcs_grid_dim.y, (fcs_int)fcs_grid_dim.z); ASSERT_FCS(res); } if (fcs_p2nfft_intpol_order) { res = fcs_p2nfft_set_pnfft_interpolation_order(handle, (fcs_int)fcs_p2nfft_intpol_order); ASSERT_FCS(res); } if (fcs_p2nfft_epsI) { res = fcs_p2nfft_set_epsI(handle, (fcs_float)fcs_p2nfft_epsI); ASSERT_FCS(res); } //res = fcs_p2nfft_set_pnfft_window_by_name(handle, "bspline"); //ASSERT_FCS(res); break; #endif #ifdef FCS_ENABLE_VMG case FCS_METH_VMG: if (fcs_vmg_near_field_cells) { res = fcs_vmg_set_near_field_cells(handle, (fcs_int)fcs_vmg_near_field_cells); ASSERT_FCS(res); } if (fcs_vmg_interpol_order) { res = fcs_vmg_set_interpolation_order(handle, (fcs_int)fcs_vmg_interpol_order); ASSERT_FCS(res); } if (fcs_vmg_discr_order) { res = fcs_vmg_set_discretization_order(handle, (fcs_int)fcs_vmg_discr_order); ASSERT_FCS(res); } if (fcs_iter_tolerance > 0) { res = fcs_vmg_set_precision(handle, (fcs_float)fcs_iter_tolerance); ASSERT_FCS(res); } break; #endif #ifdef FCS_ENABLE_PP3MG case FCS_METH_PP3MG: /* use default values, if not specified otherwise */ if (fcs_grid_dim.x) { res = fcs_pp3mg_set_cells_x(handle, (fcs_int)fcs_grid_dim.x); ASSERT_FCS(res); res = fcs_pp3mg_set_cells_y(handle, (fcs_int)fcs_grid_dim.y); ASSERT_FCS(res); res = fcs_pp3mg_set_cells_z(handle, (fcs_int)fcs_grid_dim.z); ASSERT_FCS(res); } if (fcs_pp3mg_ghosts) { res = fcs_pp3mg_set_ghosts(handle, (fcs_int)fcs_pp3mg_ghosts); ASSERT_FCS(res); } if (fcs_pp3mg_degree) { res = fcs_pp3mg_set_degree(handle, (fcs_int)fcs_pp3mg_degree); ASSERT_FCS(res); } if (fcs_pp3mg_max_part) { res = fcs_pp3mg_set_max_particles(handle, (fcs_int)fcs_pp3mg_max_part); ASSERT_FCS(res); } if (fcs_max_iter) { res = fcs_pp3mg_set_max_iterations(handle,(fcs_int)fcs_max_iter); ASSERT_FCS(res); } if (fcs_iter_tolerance > 0) { res = fcs_pp3mg_set_tol(handle, (fcs_float)fcs_iter_tolerance); ASSERT_FCS(res); } break; #endif default: error("FCS method unknown or not implemented"); break; } pack_fcs(); res = fcs_tune(handle, nloc, nloc_max, pos, chg); ASSERT_FCS(res); /* inform about tuned parameters */ switch (fcs_method) { fcs_int grid_dim[3]; fcs_float r_cut; #ifdef FCS_ENABLE_P3M case FCS_METH_P3M: res = fcs_p3m_get_r_cut(handle, &r_cut); ASSERT_FCS(res); res = fcs_p3m_get_grid(handle, grid_dim); ASSERT_FCS(res); if (0==myid) printf("FCS: Tuned grid dimensions, cutoff: %d %d %d, %f\n", grid_dim[0], grid_dim[1], grid_dim[2], r_cut); break; #endif #ifdef FCS_ENABLE_P2NFFT case FCS_METH_P2NFFT: res = fcs_p2nfft_get_grid(handle, grid_dim, grid_dim+1, grid_dim+2); ASSERT_FCS(res); res = fcs_p2nfft_get_r_cut(handle, &r_cut); ASSERT_FCS(res); if (0==myid) printf("FCS: Tuned grid dimensions, cutoff: %d %d %d, %f\n", grid_dim[0], grid_dim[1], grid_dim[2], r_cut); break; #endif #ifdef FCS_ENABLE_PP3MG case FCS_METH_PP3MG: res = fcs_pp3mg_get_cells_x(handle, grid_dim ); ASSERT_FCS(res); res = fcs_pp3mg_get_cells_y(handle, grid_dim+1); ASSERT_FCS(res); res = fcs_pp3mg_get_cells_z(handle, grid_dim+2); if (0==myid) printf("FCS: Tuned grid dimensions: %d %d %d\n", grid_dim[0], grid_dim[1], grid_dim[2]); ASSERT_FCS(res); break; #endif default: break; } /* add near-field potential, after fcs_tune */ if (0==srf) fcs_update_pottab(); }