Commit 117647fc authored by Quentin Khan's avatar Quentin Khan
Browse files

Merge branch 'development' into master

Documentation improvements
parents 65a7eb10 7a2d6614
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
// Simply create particles and try the kernels // Simply create particles and try the kernels
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
///////// PARAMETERS HANDLING //////////////////////////////////////
FHelpDescribeAndExit(argc, argv, FHelpDescribeAndExit(argc, argv,
"Driver for Chebyshev Interpolation kernel using MPI (1/r kernel). " "Driver for Chebyshev Interpolation kernel using MPI (1/r kernel). "
"Usully run using : mpirun -np nb_proc_needed ./ChebyshevInterpolationAlgorithm [params].", "Usully run using : mpirun -np nb_proc_needed ./ChebyshevInterpolationAlgorithm [params].",
...@@ -65,52 +66,55 @@ int main(int argc, char* argv[]) ...@@ -65,52 +66,55 @@ int main(int argc, char* argv[])
FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::InputFile, FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::InputFile,
FParameterDefinitions::NbThreads); FParameterDefinitions::NbThreads);
const std::string defaultFile(/*SCALFMMDataPath+*/"../Data/test20k.fma"); const std::string defaultFile("../Data/test20k.fma");
const std::string filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, defaultFile.c_str()); const std::string filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, defaultFile.c_str());
const unsigned int TreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeHeight.options, 5); const unsigned int TreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeHeight.options, 5);
const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeSubHeight.options, 2); const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeSubHeight.options, 2);
const unsigned int NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); const unsigned int NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1);
omp_set_num_threads(NbThreads); omp_set_num_threads(NbThreads);
std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl;
// //
std::cout << "Parameters "<< std::endl std::cout << "Parameters"<< std::endl
<< " Octree Depth "<< TreeHeight <<std::endl << " Octree Depth " << TreeHeight <<std::endl
<< " SubOctree depth "<< SubTreeHeight <<std::endl << " SubOctree depth " << SubTreeHeight <<std::endl
<< " Input file name: " <<filename <<std::endl << " Input file name: " << filename <<std::endl
<< " Thread number: " << NbThreads <<std::endl << " Thread count : " << NbThreads <<std::endl
<<std::endl; << std::endl;
//init values for MPI
///////// VAR INIT /////////////////////////////////////////////////
// Initialize values for MPI
FMpi app(argc,argv); FMpi app(argc,argv);
// //
// init timer // Initialize timer
FTic time; FTic time;
typedef double FReal; typedef double FReal;
FMpiFmaGenericLoader<FReal> loader(filename,app.global());
// Creation of the particle loader
FMpiFmaGenericLoader<FReal> loader(filename,app.global());
if(!loader.isOpen()) throw std::runtime_error("Particle file couldn't be opened!") ; if(!loader.isOpen()) throw std::runtime_error("Particle file couldn't be opened!") ;
////////////////////////////////////////////////////////////////////
// Begin spherical kernel
// begin spherical kernel // Accuracy
// accuracy
const unsigned int ORDER = 7; const unsigned int ORDER = 7;
// typedefs // Typedefs
typedef FP2PParticleContainerIndexed<FReal> ContainerClass; using ContainerClass = FP2PParticleContainerIndexed<FReal>;
typedef FSimpleLeaf<FReal, ContainerClass > LeafClass; using LeafClass = FSimpleLeaf<FReal, ContainerClass>;
typedef FChebCell<FReal,ORDER> CellClass; using CellClass = FChebCell<FReal,ORDER>;
typedef FOctree<FReal,CellClass,ContainerClass,LeafClass> OctreeClass; using OctreeClass = FOctree<FReal,CellClass,ContainerClass,LeafClass>;
typedef FInterpMatrixKernelR<FReal> MatrixKernelClass;
using MatrixKernel = FInterpMatrixKernelR<FReal>;
const MatrixKernelClass MatrixKernel; const MatrixKernelClass MatrixKernel;
typedef FChebSymKernel<FReal, CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass;
// using KernelClass = FChebSymKernel<FReal, CellClass,ContainerClass,MatrixKernelClass,ORDER>;
typedef FFmmAlgorithmThreadProc<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClassProc; using FmmClassProc = FFmmAlgorithmThreadProc<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass>;
// init oct-tree // Initialize empty oct-tree
OctreeClass tree(TreeHeight, SubTreeHeight, loader.getBoxWidth(), loader.getCenterOfBox()); OctreeClass tree(TreeHeight, SubTreeHeight, loader.getBoxWidth(), loader.getCenterOfBox());
...@@ -121,57 +125,75 @@ int main(int argc, char* argv[]) ...@@ -121,57 +125,75 @@ int main(int argc, char* argv[])
std::cout << "\tHeight : " << TreeHeight << " \t sub-height : " << SubTreeHeight << std::endl; std::cout << "\tHeight : " << TreeHeight << " \t sub-height : " << SubTreeHeight << std::endl;
} }
time.tic(); time.tic();
//
/* Mock particle structure to balance the tree over the processes. */
struct TestParticle{ struct TestParticle{
FSize index; FSize index; // Index of the particle in the original file.
FPoint<FReal> position; FPoint<FReal> position; // Spatial position of the particle.
FReal physicalValue; FReal physicalValue; // Physical value of the particle.
/* Returns the particle position. */
const FPoint<FReal>& getPosition(){ const FPoint<FReal>& getPosition(){
return position; return position;
} }
}; };
// Temporary array of particles read by this process.
TestParticle* particles = new TestParticle[loader.getMyNumberOfParticles()]; TestParticle* particles = new TestParticle[loader.getMyNumberOfParticles()];
memset(particles, 0, (sizeof(TestParticle) * loader.getMyNumberOfParticles())); memset(particles, 0, (sizeof(TestParticle) * loader.getMyNumberOfParticles()));
//idx (in file) of the first part that will be used by this proc. // Index (in file) of the first particle that will be read by this process.
FSize idxStart = loader.getStart(); FSize idxStart = loader.getStart();
printf("Proc %d idxStart %lld \n",app.global().processId(),idxStart); std::cout << "Proc:" << app.global().processId() << " start-index: " << idxStart << std::endl;
// Read particles from parts.
for(FSize idxPart = 0 ; idxPart < loader.getMyNumberOfParticles() ; ++idxPart){ for(FSize idxPart = 0 ; idxPart < loader.getMyNumberOfParticles() ; ++idxPart){
//Storage of the index (in the original file) of each part. // Store the index (in the original file) the particle.
particles[idxPart].index = idxPart + idxStart; particles[idxPart].index = idxPart + idxStart;
// Read particles from file // Read particle from file
loader.fillParticle(&particles[idxPart].position,&particles[idxPart].physicalValue); loader.fillParticle(&particles[idxPart].position,
&particles[idxPart].physicalValue);
} }
// Final vector of particles
FVector<TestParticle> finalParticles; FVector<TestParticle> finalParticles;
FLeafBalance balancer; FLeafBalance balancer;
// FMpiTreeBuilder< FReal,TestParticle >::ArrayToTree(app.global(), particles, loader.getMyNumberOfParticles(),
// tree.getBoxCenter(),
// tree.getBoxWidth(),
// tree.getHeight(), &finalParticles,&balancer);
FMpiTreeBuilder< FReal, TestParticle >::DistributeArrayToContainer(app.global(),particles,
loader.getMyNumberOfParticles(),
tree.getBoxCenter(),
tree.getBoxWidth(),tree.getHeight(),
&finalParticles, &balancer);
// Redistribute particules between processes
FMpiTreeBuilder< FReal, TestParticle >::
DistributeArrayToContainer(app.global(),
particles,
loader.getMyNumberOfParticles(),
tree.getBoxCenter(),
tree.getBoxWidth(),
tree.getHeight(),
&finalParticles,
&balancer);
// Free temporary array memory.
delete[] particles;
// Insert final particles into tree.
for(FSize idx = 0 ; idx < finalParticles.getSize(); ++idx){ for(FSize idx = 0 ; idx < finalParticles.getSize(); ++idx){
tree.insert(finalParticles[idx].position,finalParticles[idx].index,finalParticles[idx].physicalValue); tree.insert(finalParticles[idx].position,
finalParticles[idx].index,
finalParticles[idx].physicalValue);
} }
printf("%lld parts have been inserted in Tree \n",finalParticles.getSize());
delete[] particles;
time.tac(); time.tac();
double timeUsed = time.elapsed(); double timeUsed = time.elapsed();
double minTime,maxTime; double minTime,maxTime;
std::cout << "Done " << "(@Reading and Inserting Particles = " << time.elapsed() << "s)." << std::endl; std::cout << "Proc:" << app.global().processId()
<< " " << finalParticles.getSize()
<< "particles have been inserted in the tree. (@Reading and Inserting Particles = "
<< time.elapsed() << " s)."
<< std::endl;
MPI_Reduce(&timeUsed,&minTime,1,MPI_DOUBLE,MPI_MIN,0,app.global().getComm()); MPI_Reduce(&timeUsed,&minTime,1,MPI_DOUBLE,MPI_MIN,0,app.global().getComm());
MPI_Reduce(&timeUsed,&maxTime,1,MPI_DOUBLE,MPI_MAX,0,app.global().getComm()); MPI_Reduce(&timeUsed,&maxTime,1,MPI_DOUBLE,MPI_MAX,0,app.global().getComm());
if(app.global().processId() == 0){ if(app.global().processId() == 0){
printf("Reading and Inserting Particles Time used : \t MIN : %f \t MAX %f in s\n",minTime,maxTime); std::cout << "readinsert-time-min:" << minTime
<< "readinsert-time-max:" << maxTime
<< std::endl;
} }
} // ----------------------------------------------------- } // -----------------------------------------------------
...@@ -179,15 +201,14 @@ int main(int argc, char* argv[]) ...@@ -179,15 +201,14 @@ int main(int argc, char* argv[])
std::cout << "\nChebyshev Interpolation FMM Proc (P="<< ORDER << ") ... " << std::endl; std::cout << "\nChebyshev Interpolation FMM Proc (P="<< ORDER << ") ... " << std::endl;
time.tic(); time.tic();
//
// Here we use a pointer due to the limited size of the stack // Kernels to use (pointer because of the limited size of the stack)
//
KernelClass *kernels = new KernelClass(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox(),&MatrixKernel); KernelClass *kernels = new KernelClass(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox(),&MatrixKernel);
// // MPI FMM algorithm
FmmClassProc algorithm(app.global(),&tree, kernels); FmmClassProc algorithm(app.global(),&tree, kernels);
// // FMM exectution
algorithm.execute(); // Here the call of the FMM algorithm algorithm.execute();
//
time.tac(); time.tac();
double timeUsed = time.elapsed(); double timeUsed = time.elapsed();
double minTime,maxTime; double minTime,maxTime;
...@@ -195,9 +216,12 @@ int main(int argc, char* argv[]) ...@@ -195,9 +216,12 @@ int main(int argc, char* argv[])
MPI_Reduce(&timeUsed,&minTime,1,MPI_DOUBLE,MPI_MIN,0,app.global().getComm()); MPI_Reduce(&timeUsed,&minTime,1,MPI_DOUBLE,MPI_MIN,0,app.global().getComm());
MPI_Reduce(&timeUsed,&maxTime,1,MPI_DOUBLE,MPI_MAX,0,app.global().getComm()); MPI_Reduce(&timeUsed,&maxTime,1,MPI_DOUBLE,MPI_MAX,0,app.global().getComm());
if(app.global().processId() == 0){ if(app.global().processId() == 0){
printf("Time used : \t MIN : %f \t MAX %f \n",minTime,maxTime); std::cout << "exec-time-min:" << minTime
<< "exec-time-max:" << maxTime
<< std::endl;
} }
// Free kernels from memory
delete kernels; delete kernels;
} }
// ----------------------------------------------------- // -----------------------------------------------------
......
...@@ -48,24 +48,29 @@ ...@@ -48,24 +48,29 @@
template<class OctreeClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> template<class OctreeClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass>
class FFmmAlgorithmSectionTask : public FAbstractAlgorithm, public FAlgorithmTimers { class FFmmAlgorithmSectionTask : public FAbstractAlgorithm, public FAlgorithmTimers {
OctreeClass* const tree; //< The octree to work on OctreeClass* const tree; ///< The octree to work on
KernelClass** kernels; //< The kernels KernelClass** kernels; ///< The kernels
const int MaxThreads; const int MaxThreads;
const int OctreeHeight; const int OctreeHeight;
const int leafLevelSeperationCriteria; const int leafLevelSeparationCriteria;
public: public:
/** The constructor need the octree and the kernels used for computation /** \brief Class constructor
* @param inTree the octree to work on *
* @param inKernels the kernels to call * \note An assert checks whether one of the arguments is null.
* An assert is launched if one of the arguments is null * \param inTree the octree to work on.
*/ * \param inKernels the kernels used for computation.
FFmmAlgorithmSectionTask(OctreeClass* const inTree, KernelClass* const inKernels, const int inLeafLevelSeperationCriteria = 1) */
: tree(inTree) , kernels(0), FFmmAlgorithmSectionTask(OctreeClass* const inTree,
MaxThreads(omp_get_max_threads()), OctreeHeight(tree->getHeight()), leafLevelSeperationCriteria(inLeafLevelSeperationCriteria) KernelClass* const inKernels,
{ const int inLeafLevelSeparationCriteria = 1) :
tree(inTree) ,
kernels(0),
MaxThreads(omp_get_max_threads()),
OctreeHeight(tree->getHeight()),
leafLevelSeparationCriteria(inLeafLevelSeparationCriteria) {
FAssertLF(tree, "tree cannot be null"); FAssertLF(tree, "tree cannot be null");
FAssertLF(inKernels, "kernels cannot be null"); FAssertLF(inKernels, "kernels cannot be null");
...@@ -116,18 +121,14 @@ protected: ...@@ -116,18 +121,14 @@ protected:
} }
#pragma omp section #pragma omp section
{ {
Timers[P2PTimer].tic();
if( operationsToProceed & FFmmP2P ) directPass(); if( operationsToProceed & FFmmP2P ) directPass();
Timers[P2PTimer].tac();
} }
} }
//Timers[NearTimer].tic();
#pragma omp single #pragma omp single
{ {
if(operationsToProceed & FFmmL2P) L2PPass(); if(operationsToProceed & FFmmL2P) L2PPass();
} }
//Timers[NearTimer].tac();
} }
Timers[P2MTimer].tac(); Timers[P2MTimer].tac();
} }
...@@ -227,7 +228,7 @@ protected: ...@@ -227,7 +228,7 @@ protected:
// for each levels // for each levels
for(int idxLevel = FAbstractAlgorithm::upperWorkingLevel ; idxLevel < FAbstractAlgorithm::lowerWorkingLevel ; ++idxLevel ){ for(int idxLevel = FAbstractAlgorithm::upperWorkingLevel ; idxLevel < FAbstractAlgorithm::lowerWorkingLevel ; ++idxLevel ){
FLOG(FTic counterTimeLevel); FLOG(FTic counterTimeLevel);
const int separationCriteria = (idxLevel != FAbstractAlgorithm::lowerWorkingLevel-1 ? 1 : leafLevelSeperationCriteria); const int separationCriteria = (idxLevel != FAbstractAlgorithm::lowerWorkingLevel-1 ? 1 : leafLevelSeparationCriteria);
// for each cells // for each cells
do{ do{
const int counter = tree->getInteractionNeighbors(neighbors, octreeIterator.getCurrentGlobalCoordinate(), idxLevel, separationCriteria); const int counter = tree->getInteractionNeighbors(neighbors, octreeIterator.getCurrentGlobalCoordinate(), idxLevel, separationCriteria);
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
/** /**
* @author Berenger Bramas (berenger.bramas@inria.fr) * @author Berenger Bramas (berenger.bramas@inria.fr)
* @class FPoint<FReal>
* Please read the license * Please read the license
* *
* This class is a 3D vector. It can be used as a position * This class is a 3D vector. It can be used as a position
...@@ -36,336 +35,320 @@ ...@@ -36,336 +35,320 @@
template <class FReal> template <class FReal>
class FPoint { class FPoint {
private: private:
FReal data[3]; //< all positions x y z FReal data[3]; ///< all positions x y z
public: public:
/** Default constructor (sets position to 0/0/0) */ /** @brief Default constructor (sets position to 0/0/0) */
FPoint<FReal>(){ FPoint<FReal>(){
data[0] = data[1] = data[2] = FReal(0.0); data[0] = data[1] = data[2] = FReal(0.0);
} }
/** Constructor from an array */ /** @brief Constructor from an array */
explicit FPoint<FReal>(const FReal inPosition[3]){ explicit FPoint<FReal>(const FReal inPosition[3]){
data[0] = inPosition[0]; data[0] = inPosition[0];
data[1] = inPosition[1]; data[1] = inPosition[1];
data[2] = inPosition[2]; data[2] = inPosition[2];
} }
/** Constructor from values */ /** @brief Constructor from values */
explicit FPoint<FReal>(const FReal inX,const FReal inY,const FReal inZ){ explicit FPoint<FReal>(const FReal inX,const FReal inY,const FReal inZ){
data[0] = inX; data[0] = inX;
data[1] = inY; data[1] = inY;
data[2] = inZ; data[2] = inZ;
} }
/** /** @brief Copy constructor
* Copdata[1] constructor * @param other the source class to copy
* @param other the source class to copy */
*/
FPoint<FReal>(const FPoint<FReal>& other) { FPoint<FReal>(const FPoint<FReal>& other) {
data[0] = other.data[0]; data[0] = other.data[0];
data[1] = other.data[1]; data[1] = other.data[1];
data[2] = other.data[2]; data[2] = other.data[2];
} }
/** /** @brief Assignment operator
* Assignment operator * @param other the source class to copy
* @param other the source class to copy */
*/
FPoint<FReal>(const FPoint<FReal>& other, const FReal addset) { FPoint<FReal>(const FPoint<FReal>& other, const FReal addset) {
data[0] = other.data[0] + addset; data[0] = other.data[0] + addset;
data[1] = other.data[1] + addset; data[1] = other.data[1] + addset;
data[2] = other.data[2] + addset; data[2] = other.data[2] + addset;
} }
/** /** @brief Copy constructor
* Copdata[1] constructor * @param other the source class to copy
* @param other the source class to copy * @return this a reference to the current class
* @return this a reference to the current class */
*/
FPoint<FReal>& operator=(const FPoint<FReal>& other){ FPoint<FReal>& operator=(const FPoint<FReal>& other){
this->data[0] = other.data[0]; this->data[0] = other.data[0];
this->data[1] = other.data[1]; this->data[1] = other.data[1];
this->data[2] = other.data[2]; this->data[2] = other.data[2];
return *this; return *this;
} }
/** /** @brief Position setter
* Position setter * @param other the source class to copy
* @param other the source class to copy * @return this a reference to the current class
* @return this a reference to the current class */
*/ void setPosition(const FReal inX,const FReal inY,const FReal inZ){
void setPosition(const FReal inX,const FReal inY,const FReal inZ){ this->data[0] = inX;
this->data[0] = inX; this->data[1] = inY;
this->data[1] = inY; this->data[2] = inZ;
this->data[2] = inZ; }
}
/** @brief Get x
/** * @return this->data[0]
* Get x */
* @return this->data[0] FReal getX() const{
*/ return this->data[0];
FReal getX() const{ }
return this->data[0];
} /** @brief Get y
* @return this->data[1]
/** */
* Get y FReal getY() const{
* @return this->data[1] return this->data[1];
*/ }
FReal getY() const{
return this->data[1]; /** @brief Get z
} * @return this->data[2]
*/
/** FReal getZ() const{
* Get z return this->data[2];
* @return this->data[2] }
*/
FReal getZ() const{ /** @brief Set x
return this->data[2]; * @param the new x
} */
void setX(const FReal inX){
/** this->data[0] = inX;
* Set x }
* @param the new x
*/ /** @brief Set y
void setX(const FReal inX){ * @param the new y
this->data[0] = inX; */
} void setY(const FReal inY){
this->data[1] = inY;
/** }
* Set y
* @param the new y /** @brief Set z
*/ * @param the new z
void setY(const FReal inY){ */
this->data[1] = inY; void setZ(const FReal inZ){
} this->data[2] = inZ;
}
/**
* Set z /** @brief Add to the x-dimension the inX value
* @param the new z * @param inXthe increment in x
*/ */
void setZ(const FReal inZ){ void incX(const FReal inX){
this->data[2] = inZ; this->data[0] += inX;
} }
/** /** @brief Add to the y-dimension the inY value
* Add to the x-dimension the inX value * @param in<<<<<<y the increment in y
* @param inXthe increment in x */
*/ void incY(const FReal inY){