|
@@ -7,17 +7,18 @@
|
|
|
|
|
|
typedef std::vector<double> vec;
|
|
typedef std::vector<double> vec;
|
|
|
|
|
|
-void nbody(vec& src_coord, vec& src_value,
|
|
|
|
- vec& trg_coord, vec& trg_value,
|
|
|
|
|
|
+void nbody(vec& src_coord, vec& src_value,
|
|
|
|
+ vec& surf_coord, vec& surf_value,
|
|
|
|
+ vec& trg_coord, vec& trg_value,
|
|
const pvfmm::Kernel<double>& kernel_fn, MPI_Comm& comm){
|
|
const pvfmm::Kernel<double>& kernel_fn, MPI_Comm& comm){
|
|
int np, rank;
|
|
int np, rank;
|
|
MPI_Comm_size(comm, &np);
|
|
MPI_Comm_size(comm, &np);
|
|
MPI_Comm_rank(comm, &rank);
|
|
MPI_Comm_rank(comm, &rank);
|
|
|
|
|
|
- long long n_src_glb=0, n_src=src_coord.size()/COORD_DIM;
|
|
|
|
- long long n_trg_glb=0, n_trg=trg_coord.size()/COORD_DIM;
|
|
|
|
- MPI_Allreduce(&n_src, &n_src_glb, 1, MPI_LONG_LONG, MPI_SUM, comm);
|
|
|
|
- MPI_Allreduce(&n_trg, &n_trg_glb, 1, MPI_LONG_LONG, MPI_SUM, comm);
|
|
|
|
|
|
+ long long n_src = src_coord.size()/COORD_DIM;
|
|
|
|
+ long long n_surf = surf_coord.size()/COORD_DIM;
|
|
|
|
+ long long n_trg_glb=0, n_trg = trg_coord.size()/COORD_DIM;
|
|
|
|
+ MPI_Allreduce(&n_trg , & n_trg_glb, 1, MPI_LONG_LONG, MPI_SUM, comm);
|
|
|
|
|
|
vec glb_trg_coord(n_trg_glb*COORD_DIM);
|
|
vec glb_trg_coord(n_trg_glb*COORD_DIM);
|
|
vec glb_trg_value(n_trg_glb*kernel_fn.ker_dim[1],0);
|
|
vec glb_trg_value(n_trg_glb*kernel_fn.ker_dim[1],0);
|
|
@@ -39,8 +40,14 @@ void nbody(vec& src_coord, vec& src_value,
|
|
for(int i=0;i<omp_p;i++){
|
|
for(int i=0;i<omp_p;i++){
|
|
size_t a=( i *n_trg_glb)/omp_p;
|
|
size_t a=( i *n_trg_glb)/omp_p;
|
|
size_t b=((i+1)*n_trg_glb)/omp_p;
|
|
size_t b=((i+1)*n_trg_glb)/omp_p;
|
|
|
|
+
|
|
|
|
+ if(kernel_fn.ker_poten!=NULL)
|
|
kernel_fn.ker_poten(& src_coord[0] , n_src, &src_value[0], 1,
|
|
kernel_fn.ker_poten(& src_coord[0] , n_src, &src_value[0], 1,
|
|
&glb_trg_coord[0]+a*COORD_DIM, b-a, &glb_trg_value_[0]+a*kernel_fn.ker_dim[1],NULL);
|
|
&glb_trg_coord[0]+a*COORD_DIM, b-a, &glb_trg_value_[0]+a*kernel_fn.ker_dim[1],NULL);
|
|
|
|
+
|
|
|
|
+ if(kernel_fn.dbl_layer_poten!=NULL)
|
|
|
|
+ kernel_fn.dbl_layer_poten(& surf_coord[0] , n_surf, &surf_value[0], 1,
|
|
|
|
+ &glb_trg_coord[0]+a*COORD_DIM, b-a, &glb_trg_value_[0]+a*kernel_fn.ker_dim[1],NULL);
|
|
}
|
|
}
|
|
MPI_Allreduce(&glb_trg_value_[0], &glb_trg_value[0], glb_trg_value.size(), MPI_DOUBLE, MPI_SUM, comm);
|
|
MPI_Allreduce(&glb_trg_value_[0], &glb_trg_value[0], glb_trg_value.size(), MPI_DOUBLE, MPI_SUM, comm);
|
|
}
|
|
}
|
|
@@ -56,18 +63,22 @@ void fmm_test(size_t N, int mult_order, MPI_Comm comm){
|
|
const pvfmm::Kernel<double>& kernel_fn_aux=pvfmm::laplace_potn_d;
|
|
const pvfmm::Kernel<double>& kernel_fn_aux=pvfmm::laplace_potn_d;
|
|
|
|
|
|
// Create target and source vectors.
|
|
// Create target and source vectors.
|
|
- vec trg_coord=point_distrib<double>(RandUnif,N,comm);
|
|
|
|
- vec src_coord=point_distrib<double>(RandUnif,N,comm);
|
|
|
|
- size_t n_src=src_coord.size()/COORD_DIM;
|
|
|
|
- size_t n_trg=trg_coord.size()/COORD_DIM;
|
|
|
|
|
|
+ vec trg_coord=point_distrib<double>(RandUnif,N,comm);
|
|
|
|
+ vec src_coord=point_distrib<double>(RandUnif,N,comm);
|
|
|
|
+ vec surf_coord=point_distrib<double>(RandUnif,0,comm);
|
|
|
|
+ size_t n_trg = trg_coord.size()/COORD_DIM;
|
|
|
|
+ size_t n_src = src_coord.size()/COORD_DIM;
|
|
|
|
+ size_t n_surf=surf_coord.size()/COORD_DIM;
|
|
|
|
|
|
// Set source charges.
|
|
// Set source charges.
|
|
- vec src_value(n_src*kernel_fn.ker_dim[0]);
|
|
|
|
- for(size_t i=0;i<src_value.size();i++) src_value[i]=drand48();
|
|
|
|
|
|
+ vec src_value( n_src* kernel_fn.ker_dim[0]);
|
|
|
|
+ vec surf_value(n_surf*(kernel_fn.ker_dim[0]+COORD_DIM));
|
|
|
|
+ for(size_t i=0;i< src_value.size();i++) src_value[i]=drand48();
|
|
|
|
+ for(size_t i=0;i<surf_value.size();i++) surf_value[i]=drand48();
|
|
|
|
|
|
// Construct tree.
|
|
// Construct tree.
|
|
size_t max_pts=300;
|
|
size_t max_pts=300;
|
|
- pvfmm::PtFMM_Tree* tree=PtFMM_CreateTree(src_coord, src_value, trg_coord, comm, max_pts, pvfmm::FreeSpace);
|
|
|
|
|
|
+ pvfmm::PtFMM_Tree* tree=PtFMM_CreateTree(src_coord, src_value, surf_coord, surf_value, trg_coord, comm, max_pts, pvfmm::FreeSpace);
|
|
|
|
|
|
// Load matrices.
|
|
// Load matrices.
|
|
pvfmm::PtFMM matrices;
|
|
pvfmm::PtFMM matrices;
|
|
@@ -82,15 +93,16 @@ void fmm_test(size_t N, int mult_order, MPI_Comm comm){
|
|
|
|
|
|
// Re-run FMM
|
|
// Re-run FMM
|
|
tree->ClearFMMData();
|
|
tree->ClearFMMData();
|
|
- for(size_t i=0;i<src_value.size();i++) src_value[i]=drand48();
|
|
|
|
- PtFMM_Evaluate(tree, trg_value, n_trg, &src_value);
|
|
|
|
|
|
+ for(size_t i=0;i< src_value.size();i++) src_value[i]=drand48();
|
|
|
|
+ for(size_t i=0;i<surf_value.size();i++) surf_value[i]=drand48();
|
|
|
|
+ PtFMM_Evaluate(tree, trg_value, n_trg, &src_value, &surf_value);
|
|
|
|
|
|
{// Check error
|
|
{// Check error
|
|
vec trg_sample_coord;
|
|
vec trg_sample_coord;
|
|
vec trg_sample_value;
|
|
vec trg_sample_value;
|
|
size_t n_trg_sample=0;
|
|
size_t n_trg_sample=0;
|
|
{ // Sample target points for verifications.
|
|
{ // Sample target points for verifications.
|
|
- size_t n_skip=N*n_src/1e9;
|
|
|
|
|
|
+ size_t n_skip=N*n_trg/1e9;
|
|
if(!n_skip) n_skip=1;
|
|
if(!n_skip) n_skip=1;
|
|
for(size_t i=0;i<n_trg;i=i+n_skip){
|
|
for(size_t i=0;i<n_trg;i=i+n_skip){
|
|
for(size_t j=0;j<COORD_DIM;j++)
|
|
for(size_t j=0;j<COORD_DIM;j++)
|
|
@@ -104,12 +116,13 @@ void fmm_test(size_t N, int mult_order, MPI_Comm comm){
|
|
// Direct n-body
|
|
// Direct n-body
|
|
vec trg_sample_value_(n_trg_sample*kernel_fn.ker_dim[1]);
|
|
vec trg_sample_value_(n_trg_sample*kernel_fn.ker_dim[1]);
|
|
nbody( src_coord, src_value ,
|
|
nbody( src_coord, src_value ,
|
|
|
|
+ surf_coord, surf_value ,
|
|
trg_sample_coord, trg_sample_value_, kernel_fn, comm);
|
|
trg_sample_coord, trg_sample_value_, kernel_fn, comm);
|
|
|
|
|
|
// Compute error
|
|
// Compute error
|
|
double max_err=0, max_val=0;
|
|
double max_err=0, max_val=0;
|
|
double max_err_glb=0, max_val_glb=0;
|
|
double max_err_glb=0, max_val_glb=0;
|
|
- for(size_t i=0;i<n_trg_sample;i++){
|
|
|
|
|
|
+ for(size_t i=0;i<n_trg_sample*kernel_fn.ker_dim[1];i++){
|
|
if(fabs(trg_sample_value_[i]-trg_sample_value[i])>max_err)
|
|
if(fabs(trg_sample_value_[i]-trg_sample_value[i])>max_err)
|
|
max_err=fabs(trg_sample_value_[i]-trg_sample_value[i]);
|
|
max_err=fabs(trg_sample_value_[i]-trg_sample_value[i]);
|
|
if(fabs(trg_sample_value_[i])>max_val)
|
|
if(fabs(trg_sample_value_[i])>max_val)
|
|
@@ -141,6 +154,7 @@ with Laplace Gradient kernel, using the PvFMM library.\n");
|
|
size_t N=(size_t)strtod(commandline_option(argc, argv, "-N", "1", true, "-N <int> : Number of source and target points."),NULL);
|
|
size_t N=(size_t)strtod(commandline_option(argc, argv, "-N", "1", true, "-N <int> : Number of source and target points."),NULL);
|
|
int m= strtoul(commandline_option(argc, argv, "-m", "10", false, "-m <int> = (10) : Multipole order (+ve even integer)."),NULL,10);
|
|
int m= strtoul(commandline_option(argc, argv, "-m", "10", false, "-m <int> = (10) : Multipole order (+ve even integer)."),NULL,10);
|
|
commandline_option_end(argc, argv);
|
|
commandline_option_end(argc, argv);
|
|
|
|
+ pvfmm::Profile::Enable(true);
|
|
|
|
|
|
// Run FMM with above options.
|
|
// Run FMM with above options.
|
|
fmm_test(N, m, comm);
|
|
fmm_test(N, m, comm);
|