Commit 59df215d authored by COULAUD Olivier's avatar COULAUD Olivier

Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/scalfmm/scalfmm

# By Pierre Blanchard (4) and piacibel (4)
# Via Pierre Blanchard
* 'master' of git+ssh://scm.gforge.inria.fr//gitroot/scalfmm/scalfmm:
  Implemented M2P and P2L translations for AdaptUnifKernel.
  Provided a function to test if tree is empty.
  Provided error computation for the AdaptUnifFMM test, provided a dense version for the UnifKernel, some fixes in AdaptUnifKernel.
  changes to use -t option to set nb thread + minor bug in Block version
  testSphericalBlasBlocProc and testSphericalBlasProc added, can be used for benchmark purposes
  Changes for Matrix Kernel Class
  Implemented dense variant (i.e. no FFT) of P2M, M2M, M2L, L2L and L2P routines for Adaptive Uniform kernel (TODO M2P,P2L).
  new unit test for spherical blas
parents f20a82aa eb759b06
This diff is collapsed.
8 8
20 10 0 0 0
-0.381596 -0.909478 -1.65028 7.82637e-06 2.541938222 1.557606994e-06 3.489201182e-06 1.9909474e-07
-0.328097 -0.475796 -8.1607 0.131538 1.119259139 0.0008908943508 0.004579383445 0.02555980285
0.773946 -0.488975 4.02381 0.755605 3.011973162 -1.45016502 -1.652190245 -2.411831961
0.841093 0.258549 -4.75094 0.45865 1.98990251 -0.2577510645 0.03655161637 0.1546151569
-0.631449 -0.695168 -3.43532 0.532767 2.15223708 0.07790438363 0.2755104636 -0.006342371017
0.855311 0.420252 3.03037 0.218959 2.376001959 -0.03848747137 -0.1167391388 0.07418806718
-0.0908349 0.632258 7.69414 0.0470446 5.012127274 0.9218738946 -0.04010423188 0.4409636235
-0.837853 0.118 5.3299 0.678865 1.634756411 0.1767291196 -0.03509828097 -0.1226211785
-0.565994 0.690639 -4.50186 0.679296 2.910213541 -1.257188682 -1.850335729 -0.5607101455
0.799983 -0.599417 -0.269652 0.934693 1.907152543 -0.2129228855 0.2885587276 -0.02844632625
-0.42005 0.906916 0.325839 0.383502 2.89458325 0.434894857 0.007264147335 -0.595471763
-0.101258 0.994787 -0.120466 0.519416 2.798499163 -0.3339421311 -0.2683887681 0.3091350594
-0.164731 0.958734 -2.31716 0.830965 2.092163739 -0.003599627918 -0.1920184011 0.01079716782
-0.973424 0.221148 0.594948 0.0345721 2.634378832 0.02483866798 0.01471930828 -0.01397072505
0.532694 0.535145 6.55635 0.0534616 2.001048773 -0.01524642715 -0.004049037322 0.001833595101
0.626587 -0.682149 3.76911 0.5297 3.660159952 1.30712139 1.873943426 2.287116347
0.0663265 0.625817 7.77144 0.671149 1.431005579 -0.9270508856 0.007352727933 -0.6234777785
-0.951257 -0.0795204 -2.9797 0.00769819 2.98995399 0.005367080118 -0.001040743771 -0.003162173107
-0.764777 0.449732 -4.61365 0.383416 3.753458481 1.512786443 1.666239546 0.9383888638
-0.23121 0.970786 -0.641653 0.0668422 3.441324218 0.03394590788 -0.01475826149 0.123436539
......@@ -123,7 +123,7 @@ int main(int argc, char* argv[])
typedef FChebCell<ORDER> CellClass;
typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass;
typedef FInterpMatrixKernelR MatrixKernelClass;
const MatrixKernelClass MatrixKernel;
typedef FChebSymKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass;
//
......@@ -194,7 +194,7 @@ int main(int argc, char* argv[])
//
// Here we use a pointer due to the limited size of the stack
//
KernelClass *kernels = new KernelClass(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox());
KernelClass *kernels = new KernelClass(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox(),&MatrixKernel);
//
FmmClassProc algorithm(app.global(),&tree, kernels);
//
......
This diff is collapsed.
......@@ -229,6 +229,13 @@ public:
return getCoordinateFromPosition(position).getMortonIndex(leafIndex);
}
/*
* Indicate if tree is empty or not.
*/
bool isEmpty(){
return root->getRightLeafIndex() < 0;
}
/**
* The class works on suboctree. Most of the resources needed
* are avaiblable by using FAbstractSubOctree. But when accessing
......
......@@ -72,6 +72,27 @@ protected:
BoxCorner.getZ() + (FReal(Coordinate.getZ()) + FReal(.5)) * BoxWidthLeaf);
}
/**
* @brief Return the position of the center of a cell from its tree
* coordinate
* @param FTreeCoordinate
* @param inLevel the current level of Cell
*/
FPoint getCellCenter(const FTreeCoordinate coordinate, int inLevel)
{
//Set the boxes width needed
FReal widthAtCurrentLevel = BoxWidthLeaf*FReal(1 << (TreeHeight-(inLevel+1)));
FReal widthAtCurrentLevelDiv2 = widthAtCurrentLevel/FReal(2.);
//Set the center real coordinates from box corner and widths.
FReal X = BoxCorner.getX() + FReal(coordinate.getX())*widthAtCurrentLevel + widthAtCurrentLevelDiv2;
FReal Y = BoxCorner.getY() + FReal(coordinate.getY())*widthAtCurrentLevel + widthAtCurrentLevelDiv2;
FReal Z = BoxCorner.getZ() + FReal(coordinate.getZ())*widthAtCurrentLevel + widthAtCurrentLevelDiv2;
return FPoint(X,Y,Z);
}
public:
/**
* The constructor initializes all constant attributes and it reads the
......
This diff is collapsed.
......@@ -93,8 +93,8 @@ int main(int argc, char ** argv){
std::cout << ">> This executable has to be used to test the FMM algorithm.\n";
//////////////////////////////////////////////////////////////
//
const int NbLevels = FParameters::getValue(argc,argv,"-depth", 7);
const int SizeSubLevels = FParameters::getValue(argc,argv,"subdepth", 3);
const int NbLevels = FParameters::getValue(argc,argv,"-depth", 3);
const int SizeSubLevels = FParameters::getValue(argc,argv,"subdepth", 2);
const int sminM = FParameters::getValue(argc,argv,"-sM", P*P*P);
const int sminL = FParameters::getValue(argc,argv,"-sL", P*P*P);
//
......@@ -105,7 +105,7 @@ int main(int argc, char ** argv){
//////////////////////////////////////////////////////////////////////////////////
// Not Random Loader
//////////////////////////////////////////////////////////////////////////////////
const std::string fileName(FParameters::getStr(argc,argv,"-fin", "../Data/prolate50.fma"));
const std::string fileName(FParameters::getStr(argc,argv,"-fin", "../Data/prolate50.out.fma"));
FFmaGenericLoader loader(fileName);
const long int NbPart = loader.getNumberOfParticles() ;
// Random Loader
......@@ -123,26 +123,28 @@ int main(int argc, char ** argv){
std::cout << " criteria SM: "<< sminM <<std::endl
<< " criteria SL: "<< sminL <<std::endl <<std::endl;
//
{
counter.tic();
FReal L= loader.getBoxWidth();
FmaRParticle* particles= new FmaRParticle[NbPart];
FPoint minPos(L,L,L), maxPos(-L,-L,-L);
//
loader.fillParticle(particles,NbPart);
for(int idxPart = 0 ; idxPart < NbPart; ++idxPart){
const FPoint PP(particles[idxPart].getPosition() ) ;
//
minPos.setX(FMath::Min(minPos.getX(),PP.getX())) ;
minPos.setY(FMath::Min(minPos.getY(),PP.getY())) ;
minPos.setZ(FMath::Min(minPos.getZ(),PP.getZ())) ;
maxPos.setX(FMath::Max(maxPos.getX(),PP.getX())) ;
maxPos.setY(FMath::Max(maxPos.getY(),PP.getY())) ;
maxPos.setZ(FMath::Max(maxPos.getZ(),PP.getZ())) ;
//
tree.insert(PP, idxPart, particles[idxPart].getPhysicalValue());
}
counter.tic();
FReal L= loader.getBoxWidth();
//FmaRParticle* particles= new FmaRParticle[NbPart];
FmaRWParticle<8,8>* const particles = new FmaRWParticle<8,8>[NbPart];
FPoint minPos(L,L,L), maxPos(-L,-L,-L);
//
loader.fillParticle(particles,NbPart);
for(int idxPart = 0 ; idxPart < NbPart; ++idxPart){
const FPoint PP(particles[idxPart].getPosition() ) ;
//
minPos.setX(FMath::Min(minPos.getX(),PP.getX())) ;
minPos.setY(FMath::Min(minPos.getY(),PP.getY())) ;
minPos.setZ(FMath::Min(minPos.getZ(),PP.getZ())) ;
maxPos.setX(FMath::Max(maxPos.getX(),PP.getX())) ;
maxPos.setY(FMath::Max(maxPos.getY(),PP.getY())) ;
maxPos.setZ(FMath::Max(maxPos.getZ(),PP.getZ())) ;
//
tree.insert(PP, idxPart, particles[idxPart].getPhysicalValue());
counter.tac();
......@@ -163,6 +165,58 @@ int main(int argc, char ** argv){
counter.tac();
std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << " s)." << std::endl;
//
FReal energy= 0.0 , energyD = 0.0 ;
/////////////////////////////////////////////////////////////////////////////////////////////////
// Compute direct energy
/////////////////////////////////////////////////////////////////////////////////////////////////
for(int idx = 0 ; idx < loader.getNumberOfParticles() ; ++idx){
energyD += particles[idx].getPotential()*particles[idx].getPhysicalValue() ;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Compare
/////////////////////////////////////////////////////////////////////////////////////////////////
FMath::FAccurater potentialDiff;
FMath::FAccurater fx, fy, fz;
{ // Check that each particle has been summed with all other
// std::cout << "indexPartOrig || DIRECT V fx || FMM V fx" << std::endl;
tree.forEachLeaf([&](LeafClass* leaf){
const FReal*const potentials = leaf->getTargets()->getPotentials();
const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues();
const FReal*const forcesX = leaf->getTargets()->getForcesX();
const FReal*const forcesY = leaf->getTargets()->getForcesY();
const FReal*const forcesZ = leaf->getTargets()->getForcesZ();
const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles();
const FVector<int>& indexes = leaf->getTargets()->getIndexes();
for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){
const int indexPartOrig = indexes[idxPart];
potentialDiff.add(particles[indexPartOrig].getPotential(),potentials[idxPart]);
fx.add(particles[indexPartOrig].getForces()[0],forcesX[idxPart]);
fy.add(particles[indexPartOrig].getForces()[1],forcesY[idxPart]);
fz.add(particles[indexPartOrig].getForces()[2],forcesZ[idxPart]);
energy += potentials[idxPart]*physicalValues[idxPart];
// std::cout << indexPartOrig
// << " " << particles[indexPartOrig].getPotential() << " " << particles[indexPartOrig].getForces()[0]
// << " " << potentials[idxPart] << " " << forcesX[idxPart]
// << std::endl;
}
});
}
delete[] particles;
// Print for information
std::cout << "Potential " << potentialDiff << std::endl;
std::cout << "Fx " << fx << std::endl;
std::cout << "Fy " << fy << std::endl;
std::cout << "Fz " << fz << std::endl;
OctreeClass::Iterator octreeIterator(&tree);
std::ofstream file("aa.tree", std::ofstream::out );
......
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Berenger Bramas, Matthias Messner
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info".
// "http://www.gnu.org/licenses".
// ===================================================================================
// ==== CMAKE =====
// @FUSE_MPI
// @FUSE_BLAS
// ================
#include "../../Src/Utils/FTic.hpp"
#include "../../Src/Utils/FMpi.hpp"
#include "../../Src/Utils/FParameters.hpp"
#include "../../Src/Utils/FMath.hpp"
#include "../../Src/Containers/FOctree.hpp"
#include "../../Src/Containers/FVector.hpp"
#include "../../Src/Kernels/Spherical/FSphericalBlockBlasKernel.hpp"
#include "../../Src/Kernels/Spherical/FSphericalCell.hpp"
#include "../../Src/Kernels/Rotation/FRotationKernel.hpp"
#include "../../Src/Kernels/Rotation/FRotationCell.hpp"
#include "../../Src/Core/FFmmAlgorithmThreadProc.hpp"
#include "../../Src/Core/FFmmAlgorithmThread.hpp"
#include "../../Src/Components/FSimpleLeaf.hpp"
#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp"
#include "../../Src/Files/FMpiFmaGenericLoader.hpp"
#include "../../Src/Files/FMpiTreeBuilder.hpp"
#include "../../Src/BalanceTree/FLeafBalance.hpp"
// Simply create particles and try the kernels
int main(int argc, char ** argv){
typedef FSphericalCell CellClass;
typedef FP2PParticleContainer<> ContainerClass;
typedef FSimpleLeaf< ContainerClass > LeafClass;
typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass;
typedef FSphericalBlockBlasKernel< CellClass, ContainerClass > KernelClass;
typedef FFmmAlgorithmThreadProc<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass;
typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassNoProc;
///////////////////////What we do/////////////////////////////
std::cout << ">> This executable has to be used to test Spherical algorithm.\n";
//////////////////////////////////////////////////////////////
FMpi app( argc, argv);
const int DevP = FParameters::getValue(argc,argv,"-p", 8);
const int NbLevels = FParameters::getValue(argc,argv,"-depth", 5);
const int SizeSubLevels = FParameters::getValue(argc,argv,"-subdepth", 3);
FTic counter;
const char* const defaultFilename = (sizeof(FReal) == sizeof(float))?
"../Data/test20k.bin.fma.single":
"../Data/test20k.bin.fma.double";
const char* const filename = FParameters::getStr(argc,argv,"-f", defaultFilename);
const int nbThreads = FParameters::getValue(argc,argv,"-t",8);
omp_set_num_threads(nbThreads);
std::cout << "Opening : " << filename << "\n";
FMpiFmaGenericLoader loader(filename, app.global());
if(!loader.isOpen()){
std::cout << "Loader Error, " << filename << " is missing\n";
return 1;
}
CellClass::Init(DevP,true);
OctreeClass tree(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox());
// -----------------------------------------------------
std::cout << "Creating & Inserting " << loader.getNumberOfParticles() << " particles ..." << std::endl;
std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl;
counter.tic();
if( app.global().processCount() != 1){
//////////////////////////////////////////////////////////////////////////////////
// Build tree from mpi loader
//////////////////////////////////////////////////////////////////////////////////
std::cout << "Build Tree ..." << std::endl;
counter.tic();
struct TestParticle{
FPoint position;
FReal physicalValue;
const FPoint& getPosition(){
return position;
}
};
TestParticle* particles = new TestParticle[loader.getNumberOfParticles()];
memset(particles, 0, sizeof(TestParticle) * loader.getNumberOfParticles());
for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
loader.fillParticle(&particles[idxPart].position,&particles[idxPart].physicalValue);
}
FVector<TestParticle> finalParticles;
FLeafBalance balancer;
// FMpiTreeBuilder< TestParticle >::ArrayToTree(app.global(), particles, loader.getNumberOfParticles(),
// tree.getBoxCenter(),
// tree.getBoxWidth(),
// tree.getHeight(), &finalParticles,&balancer);
FMpiTreeBuilder< TestParticle >::DistributeArrayToContainer(app.global(),particles,
loader.getMyNumberOfParticles(),
tree.getBoxCenter(),
tree.getBoxWidth(),tree.getHeight(),
&finalParticles, &balancer);
for(int idx = 0 ; idx < finalParticles.getSize(); ++idx){
tree.insert(finalParticles[idx].position,finalParticles[idx].physicalValue);
}
delete[] particles;
counter.tac();
std::cout << "Done " << "(" << counter.elapsed() << "s)." << std::endl;
//////////////////////////////////////////////////////////////////////////////////
}
else{
FPoint position;
FReal physicalValue;
for(FSize idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
loader.fillParticle(&position,&physicalValue);
tree.insert(position, physicalValue);
}
}
counter.tac();
std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl;
// -----------------------------------------------------
std::cout << "Create kernel..." << std::endl;
KernelClass kernels(DevP, NbLevels,loader.getBoxWidth(), loader.getCenterOfBox());
std::cout << "Done " << " in " << counter.elapsed() << "s)." << std::endl;
// -----------------------------------------------------
std::cout << "Working on particles ..." << std::endl;
FmmClass algo(app.global(),&tree,&kernels);
counter.tic();
algo.execute();
counter.tac();
std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl;
{ // get sum forces&potential
FTRACE( FTrace::FFunction functionTrace(__FUNCTION__, "Sum Result" , __FILE__ , __LINE__) );
FReal potential = 0;
FReal fx = 0.0, fy = 0.0, fz = 0.0;
tree.forEachLeaf([&](LeafClass* leaf){
const FReal*const potentials = leaf->getTargets()->getPotentials();
const FReal*const forcesX = leaf->getTargets()->getForcesX();
const FReal*const forcesY = leaf->getTargets()->getForcesY();
const FReal*const forcesZ = leaf->getTargets()->getForcesZ();
const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles();
for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){
potential += potentials[idxPart];
fx += forcesX[idxPart];
fy += forcesY[idxPart];
fz += forcesZ[idxPart];
}
});
std::cout << "My potential is " << potential << std::endl;
potential = app.global().reduceSum(potential);
fx = app.global().reduceSum(fx);
fy = app.global().reduceSum(fy);
fz = app.global().reduceSum(fz);
if(app.global().processId() == 0){
std::cout << "Foces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl;
std::cout << "Potential Sum = " << potential << std::endl;
}
}
return 0;
}
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Berenger Bramas, Matthias Messner
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info".
// "http://www.gnu.org/licenses".
// ===================================================================================
// ==== CMAKE =====
// @FUSE_MPI
// @FUSE_BLAS
// ================
#include "../../Src/Utils/FTic.hpp"
#include "../../Src/Utils/FMpi.hpp"
#include "../../Src/Utils/FParameters.hpp"
#include "../../Src/Utils/FMath.hpp"
#include "../../Src/Containers/FOctree.hpp"
#include "../../Src/Containers/FVector.hpp"
#include "../../Src/Kernels/Spherical/FSphericalBlasKernel.hpp"
#include "../../Src/Kernels/Spherical/FSphericalCell.hpp"
#include "../../Src/Kernels/Rotation/FRotationKernel.hpp"
#include "../../Src/Kernels/Rotation/FRotationCell.hpp"
#include "../../Src/Core/FFmmAlgorithmThreadProc.hpp"
#include "../../Src/Core/FFmmAlgorithmThread.hpp"
#include "../../Src/Components/FSimpleLeaf.hpp"
#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp"
#include "../../Src/Files/FMpiFmaGenericLoader.hpp"
#include "../../Src/Files/FMpiTreeBuilder.hpp"
#include "../../Src/BalanceTree/FLeafBalance.hpp"
// Simply create particles and try the kernels
int main(int argc, char ** argv){
typedef FSphericalCell CellClass;
typedef FP2PParticleContainer<> ContainerClass;
typedef FSimpleLeaf< ContainerClass > LeafClass;
typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass;
typedef FSphericalBlasKernel< CellClass, ContainerClass > KernelClass;
typedef FFmmAlgorithmThreadProc<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass;
typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassNoProc;
///////////////////////What we do/////////////////////////////
std::cout << ">> This executable has to be used to test Spherical algorithm.\n";
//////////////////////////////////////////////////////////////
FMpi app( argc, argv);
const int DevP = FParameters::getValue(argc,argv,"-p", 8);
const int NbLevels = FParameters::getValue(argc,argv,"-depth", 5);
const int SizeSubLevels = FParameters::getValue(argc,argv,"-subdepth", 3);
FTic counter;
const char* const defaultFilename = (sizeof(FReal) == sizeof(float))?
"../Data/test20k.bin.fma.single":
"../Data/test20k.bin.fma.double";
const char* const filename = FParameters::getStr(argc,argv,"-f", defaultFilename);
const int nbThreads = FParameters::getValue(argc,argv,"-t",8);
omp_set_num_threads(nbThreads);
std::cout << "Opening : " << filename << "\n";
FMpiFmaGenericLoader loader(filename, app.global());
if(!loader.isOpen()){
std::cout << "Loader Error, " << filename << " is missing\n";
return 1;
}
CellClass::Init(DevP);
OctreeClass tree(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox());
// -----------------------------------------------------
std::cout << "Creating & Inserting " << loader.getNumberOfParticles() << " particles ..." << std::endl;
std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl;
counter.tic();
if( app.global().processCount() != 1){
//////////////////////////////////////////////////////////////////////////////////
// Build tree from mpi loader
//////////////////////////////////////////////////////////////////////////////////
std::cout << "Build Tree ..." << std::endl;
counter.tic();
struct TestParticle{
FPoint position;
FReal physicalValue;
const FPoint& getPosition(){
return position;
}
};
TestParticle* particles = new TestParticle[loader.getNumberOfParticles()];
memset(particles, 0, sizeof(TestParticle) * loader.getNumberOfParticles());
for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
loader.fillParticle(&particles[idxPart].position,&particles[idxPart].physicalValue);
}
FVector<TestParticle> finalParticles;
FLeafBalance balancer;
// FMpiTreeBuilder< TestParticle >::ArrayToTree(app.global(), particles, loader.getNumberOfParticles(),
// tree.getBoxCenter(),
// tree.getBoxWidth(),
// tree.getHeight(), &finalParticles,&balancer);
FMpiTreeBuilder< TestParticle >::DistributeArrayToContainer(app.global(),particles,
loader.getMyNumberOfParticles(),
tree.getBoxCenter(),
tree.getBoxWidth(),tree.getHeight(),
&finalParticles, &balancer);
for(int idx = 0 ; idx < finalParticles.getSize(); ++idx){
tree.insert(finalParticles[idx].position,finalParticles[idx].physicalValue);
}
delete[] particles;
counter.tac();
std::cout << "Done " << "(" << counter.elapsed() << "s)." << std::endl;
//////////////////////////////////////////////////////////////////////////////////
}
else{
FPoint position;
FReal physicalValue;
for(FSize idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
loader.fillParticle(&position,&physicalValue);
tree.insert(position, physicalValue);
}
}
counter.tac();
std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl;
// -----------------------------------------------------
std::cout << "Create kernel..." << std::endl;
KernelClass kernels(DevP, NbLevels,loader.getBoxWidth(), loader.getCenterOfBox());
std::cout << "Done " << " in " << counter.elapsed() << "s)." << std::endl;
// -----------------------------------------------------
std::cout << "Working on particles ..." << std::endl;
FmmClass algo(app.global(),&tree,&kernels);
counter.tic();
algo.execute();
counter.tac();
std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl;
{ // get sum forces&potential
FTRACE( FTrace::FFunction functionTrace(__FUNCTION__, "Sum Result" , __FILE__ , __LINE__) );
FReal potential = 0;
FReal fx = 0.0, fy = 0.0, fz = 0.0;
tree.forEachLeaf([&](LeafClass* leaf){
const FReal*const potentials = leaf->getTargets()->getPotentials();
const FReal*const forcesX = leaf->getTargets()->getForcesX();
const FReal*const forcesY = leaf->getTargets()->getForcesY();
const FReal*const forcesZ = leaf->getTargets()->getForcesZ();
const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles();
for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){
potential += potentials[idxPart];
fx += forcesX[idxPart];
fy += forcesY[idxPart];