diff --git a/Examples/ChebyshevInterpolationFMM.cpp b/Examples/ChebyshevInterpolationFMM.cpp index d2b7f06338737f2911d97fa9f1d57188ae917e3a..66a53e047af52c7f06096a7a3c53a0ae385e1dac 100755 --- a/Examples/ChebyshevInterpolationFMM.cpp +++ b/Examples/ChebyshevInterpolationFMM.cpp @@ -45,6 +45,8 @@ #include "Core/FFmmAlgorithm.hpp" #endif +#include "../Src/Utils/FParameterNames.hpp" + /** * This program runs the FMM Algorithm with the Chebyshev kernel and compares the results with a direct computation. */ @@ -54,40 +56,25 @@ //! \authors B. Bramas, O. Coulaud //! //! This code is a short example to use the Chebyshev Interpolation approach for the 1/r kernel -//! -//!@Algorithm -//! <b> General arguments:</b> -//! \param -help(-h) to see the parameters available in this driver -//! \param -depth The depth of the octree -//! \param -subdepth Specifies the size of the sub octree -//! \param -t The number of threads -//! -//! \param -f name Name of the particles file with extension (.fma or .bfma). The data in file have to be in our FMA format -//! -// -void usage() { - std::cout << "Driver for Chebyshev interpolation kernel (1/r kernel)" << std::endl; - std::cout << "Options "<< std::endl - << " -help to see the parameters " << std::endl - << " -depth the depth of the octree "<< std::endl - << " -subdepth specifies the size of the sub octree " << std::endl - << " -f name name specifies the name of the particle distribution" << std::endl - << " -t n specifies the number of threads used in the computations" << std::endl; -} // Simply create particles and try the kernels int main(int argc, char* argv[]) { + FHelpDescribeAndExit(argc, argv, + "Driver for Chebyshev interpolation kernel (1/r kernel).", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::InputFile, + FParameterDefinitions::NbThreads); + + const std::string defaultFile(/*SCALFMMDataPath+*/"../Data/test20k.fma" ); - const std::string filename = FParameters::getStr(argc,argv,"-f", defaultFile.c_str()); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1); - if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")){ - usage() ; - exit(EXIT_SUCCESS); - } + 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 SubTreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeSubHeight.options, 2); + const unsigned int NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); + + #ifdef _OPENMP omp_set_num_threads(NbThreads); std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; diff --git a/Examples/ChebyshevInterpolationMPIFMM.cpp b/Examples/ChebyshevInterpolationMPIFMM.cpp index b5ed965d84d5c324e17cc51fa7cad8c6dd7ee5e0..7a1157c6cb71e99ba41a7018048caf3b2ddfdc85 100644 --- a/Examples/ChebyshevInterpolationMPIFMM.cpp +++ b/Examples/ChebyshevInterpolationMPIFMM.cpp @@ -44,6 +44,7 @@ #include "../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp" #include "../Src/Utils/FParameters.hpp" +#include "../Src/Utils/FParameterNames.hpp" /// \file ChebyshevInterpolationMPIFMM @@ -52,41 +53,25 @@ //! \authors B. Bramas, O. Coulaud //! //! This code is a short example to use the FMM Algorithm Proc with Chebyshev Interpolation for the 1/r kernel -//! -//! -//! <b> General arguments:</b> -//! \param -help(-h) to see the parameters available in this driver -//! \param -depth The depth of the octree -//! \param -subdepth Specifies the size of the sub octree -//! \param -t The number of threads -//! -//! \param -f name Name of the particles file with extension (.fma or .bfma). The data in file have to be in our FMA format -//! -// -void usage() { - std::cout << "Driver for Chebyshev Interpolation kernel using MPI (1/r kernel)" << std::endl; - std::cout << "Options "<< std::endl - << " -help to see the parameters " << std::endl - << " -depth the depth of the octree "<< std::endl - << " -subdepth specifies the size of the sub octree " << std::endl - << " -f name name specifies the name of the particle distribution" << std::endl - << " -t n specifies the number of threads used in the computations" << std::endl - << " CMD >> mpirun -np nb_proc_needed ./ChebyshevInterpolationAlgorithm ....." << std::endl; -} // Simply create particles and try the kernels int main(int argc, char* argv[]) { + FHelpDescribeAndExit(argc, argv, + "Driver for Chebyshev Interpolation kernel using MPI (1/r kernel). " + "Usully run using : mpirun -np nb_proc_needed ./ChebyshevInterpolationAlgorithm [params].", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::InputFile, + FParameterDefinitions::NbThreads); + const std::string defaultFile(/*SCALFMMDataPath+*/"../Data/test20k.fma"); - const std::string filename = FParameters::getStr(argc,argv,"-f", defaultFile.c_str()); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1); - if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")){ - usage() ; - exit(-1); - } + 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 SubTreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeSubHeight.options, 2); + const unsigned int NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); + + #ifdef _OPENMP omp_set_num_threads(NbThreads); std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; diff --git a/Examples/DirectComputation.cpp b/Examples/DirectComputation.cpp index 8cc47f51d46198a291394265475c635bbeb5d33a..f76b57fcc0bd09f1d920cb8e87ccd3f27aee6ef2 100755 --- a/Examples/DirectComputation.cpp +++ b/Examples/DirectComputation.cpp @@ -31,7 +31,7 @@ #include "Kernels/P2P/FP2P.hpp" #include "Kernels/Interpolation/FInterpMatrixKernel.hpp" - +#include "../Src/Utils/FParameterNames.hpp" // /// \file DirectComputation.cpp //! @@ -49,26 +49,20 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ - // - ///////////////////////What we do///////////////////////////// - if( FParameters::existParameter(argc, argv, "-help" ) || argc < 4){ - std::cout << ">> This executable has to be used to compute interaction either for periodic or non periodic system.\n"; - std::cout << ">> Example -fin filenameIN.{fma or bfma) -fout filenameOUT{fma or bfma) \n"; - std::cout << ">> Default input file : ../Data/unitCubeXYZQ20k.fma\n"; - std::cout << " Options " << std::endl; - std::cout << " -verbose : print index x y z Q V fx fy fz " << std::endl; - std::cout << " -fin filename. Extension specifies if the file is binary or not. " << std::endl; - std::cout << " Only our FMA (.bma, .bfma) is allowed " << std::endl; - std::cout << " -fout filenameOUT output file with extension (default output.bfma)" << std::endl; - exit(-1); - - } + FHelpDescribeAndExit(argc, argv, + ">> This executable has to be used to compute interaction either for periodic or non periodic system.\n" + ">> Example -fin filenameIN.{fma or bfma) -fout filenameOUT{fma or bfma) \n" + ">> Default input file : ../Data/unitCubeXYZQ20k.fma\n" + ">> Only our FMA (.bma, .bfma) is allowed as input.\n" + ">> Output file with extension (default output.bfma).", + FParameterDefinitions::InputFile, FParameterDefinitions::OutputFile, + FParameterDefinitions::EnabledVerbose); ////////////////////////////////////////////////////////////// const std::string defaultFile(/*SCALFMMDataPath+*/"../Data/unitCubeXYZQ20k.fma"); - const std::string filenameIn(FParameters::getStr(argc,argv,"-fin", defaultFile.c_str())); - const std::string filenameOut(FParameters::getStr(argc,argv,"-fout", "output.bfma")); + const std::string filenameIn(FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, defaultFile.c_str())); + const std::string filenameOut(FParameters::getStr(argc,argv,FParameterDefinitions::OutputFile.options, "output.bfma")); // FTic counter; @@ -187,7 +181,7 @@ int main(int argc, char ** argv){ // end generate // ----------------------------------------------------- // - if(FParameters::existParameter(argc, argv, "-verbose")){ + if(FParameters::existParameter(argc, argv, FParameterDefinitions::EnabledVerbose.options)){ denergy = 0 ; for(int idx = 0 ; idx < nbParticles ; ++idx){ std::cout << ">> index " << idx << std::endl; diff --git a/Examples/RotationFMM.cpp b/Examples/RotationFMM.cpp index 07be2f2710e9094202060a2a92b6eee4c71b85f3..2fcab4b2c3c7945646e274d234733fe9d70240a3 100755 --- a/Examples/RotationFMM.cpp +++ b/Examples/RotationFMM.cpp @@ -43,6 +43,8 @@ #include "Core/FFmmAlgorithm.hpp" #endif +#include "../Src/Utils/FParameterNames.hpp" + /// \file RotationFMM.cpp //! //! \brief This program runs the FMM Algorithm with harmonic spherical approximation of 1/r kernel @@ -61,28 +63,22 @@ //! // -void usage() { - std::cout << "Driver for HArmonic Spherical + Rotation -- kernel (1/r kernel)" << std::endl; - std::cout << "Options "<< std::endl - << " -help to see the parameters " << std::endl - << " -depth the depth of the octree "<< std::endl - << " -subdepth specifies the size of the sub octree " << std::endl - << " -f name name specifies the name of the particle distribution. If extension is . bfma th file is -in binary mode" << std::endl - << " -t n specifies the number of threads used in the computations" << std::endl; -} // Simply create particles and try the kernels int main(int argc, char* argv[]) { + FHelpDescribeAndExit(argc, argv, + "Driver for HArmonic Spherical + Rotation -- kernel (1/r kernel).", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::InputFile, + FParameterDefinitions::NbThreads); + const std::string defaultFile(/*SCALFMMDataPath+*/"../Data/test20k.fma"); - const std::string filename(FParameters::getStr(argc,argv,"-f", defaultFile.c_str())); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1); - if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")){ - usage() ; - exit(-1); - } + 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 SubTreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeSubHeight.options, 2); + const unsigned int NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); + #ifdef _OPENMP omp_set_num_threads(NbThreads) ; std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; diff --git a/Examples/RotationMPIFMM.cpp b/Examples/RotationMPIFMM.cpp index c589ac823f7ed34110968cf7310ae717d7065d0a..12e66e49e7bfb0ebbdfaacaa14f5bd5d67002b47 100644 --- a/Examples/RotationMPIFMM.cpp +++ b/Examples/RotationMPIFMM.cpp @@ -43,6 +43,7 @@ #include "../../Src/Utils/FParameters.hpp" +#include "../Src/Utils/FParameterNames.hpp" /// \file RotationFMMProc.cpp //! @@ -62,186 +63,182 @@ //! // -void usage() { - std::cout << "Driver for Rotation Spherical kernel using MPI (1/r kernel)" << std::endl; - std::cout << "Options "<< std::endl - << " -help to see the parameters " << std::endl - << " -depth the depth of the octree "<< std::endl - << " -subdepth specifies the size of the sub octree " << std::endl - << " -f name name specifies the name of the particle distribution" << std::endl - << " -t n specifies the number of threads used in the computations" << std::endl - << " CMD >> mpirun -np nb_proc_needed ./RotationFMMProc ....." << std::endl; -} + // Simply create particles and try the kernels int main(int argc, char* argv[]) { - const std::string defaultFile(/*SCALFMMDataPath+*/"../Data/test20k.fma"); - const std::string filename = FParameters::getStr(argc,argv,"-f", defaultFile.c_str()); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1); - if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")){ - usage() ; - exit(-1); - } + FHelpDescribeAndExit(argc, argv, + "Driver for Rotation Spherical kernel using MPI (1/r kernel).\n" + "CMD >> mpirun -np nb_proc_needed ./RotationFMMProc [params]", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::InputFile, + FParameterDefinitions::NbThreads); + + const std::string defaultFile(/*SCALFMMDataPath+*/"../Data/test20k.fma"); + 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 SubTreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeSubHeight.options, 2); + const unsigned int NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); + + #ifdef _OPENMP - omp_set_num_threads(NbThreads); - std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; + omp_set_num_threads(NbThreads); + std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; #else - std::cout << "\n>> Sequential version.\n" << std::endl; + std::cout << "\n>> Sequential version.\n" << std::endl; #endif - // - std::cout << "Parameters "<< std::endl - << " Octree Depth "<< TreeHeight <<std::endl - << " SubOctree depth "<< SubTreeHeight <<std::endl - << " Input file name: " <<filename <<std::endl - << " Thread number: " << NbThreads <<std::endl - <<std::endl; - //init values for MPI - FMpi app(argc,argv); - // - // init timer - FTic time; - - FMpiFmaGenericLoader* loader = new FMpiFmaGenericLoader(filename,app.global()); - - if(!loader->isOpen()) throw std::runtime_error("Particle file couldn't be opened!") ; - //////////////////////////////////////////////////////////////////// - - - - // begin spherical kernel - - // accuracy - const unsigned int P = 22; - // typedefs - typedef FP2PParticleContainerIndexed<> ContainerClass; - typedef FSimpleLeaf< ContainerClass > LeafClass; - typedef FRotationCell<P> CellClass; - typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; - // - typedef FRotationKernel< CellClass, ContainerClass , P> KernelClass; - // - typedef FFmmAlgorithmThreadProc<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClassProc; - - // init oct-tree - OctreeClass tree(TreeHeight, SubTreeHeight, loader->getBoxWidth(), loader->getCenterOfBox()); - - - { // ----------------------------------------------------- - if(app.global().processId() == 0){ - std::cout << "Creating & Inserting " << loader->getNumberOfParticles() - << " particles ..." << std::endl; - std::cout << "\tHeight : " << TreeHeight << " \t sub-height : " << SubTreeHeight << std::endl; - } - time.tic(); - // - - struct TestParticle{ - int indexInFile; - FPoint position; - FReal physicalValue; - const FPoint& getPosition(){ - return position; - } - }; - TestParticle* particles = new TestParticle[loader->getMyNumberOfParticles()]; - memset(particles, 0, (unsigned int) (sizeof(TestParticle) * loader->getMyNumberOfParticles())); - - //idx (in file) of the first part that will be used by this proc. - int idxStart = loader->getStart(); - - for(int idxPart = 0 ; idxPart < loader->getMyNumberOfParticles() ; ++idxPart){ - //Storage of the index (in the original file) of each part. - particles[idxPart].indexInFile = idxPart + idxStart; - - // Read particles from file - loader->fillParticle(&particles[idxPart].position,&particles[idxPart].physicalValue); - } - - FVector<TestParticle> finalParticles; - FLeafBalance 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].indexInFile,finalParticles[idx].physicalValue); - } - - delete[] particles; - - time.tac(); - std::cout << "Done " << "(@Creating and Inserting Particles = " - << time.elapsed() << "s)." << std::endl; - } // ----------------------------------------------------- - - { // ----------------------------------------------------- - std::cout << "\nRotation harmonic Spherical FMM Proc (P="<< P << ") ... " << std::endl; - - time.tic(); // - // Here we use a pointer due to the limited size of the stack + std::cout << "Parameters "<< std::endl + << " Octree Depth "<< TreeHeight <<std::endl + << " SubOctree depth "<< SubTreeHeight <<std::endl + << " Input file name: " <<filename <<std::endl + << " Thread number: " << NbThreads <<std::endl + <<std::endl; + //init values for MPI + FMpi app(argc,argv); // - KernelClass *kernels = new KernelClass(TreeHeight, loader->getBoxWidth(), loader->getCenterOfBox()); + // init timer + FTic time; + + FMpiFmaGenericLoader* loader = new FMpiFmaGenericLoader(filename,app.global()); + + if(!loader->isOpen()) throw std::runtime_error("Particle file couldn't be opened!") ; + //////////////////////////////////////////////////////////////////// + + + + // begin spherical kernel + + // accuracy + const unsigned int P = 22; + // typedefs + typedef FP2PParticleContainerIndexed<> ContainerClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FRotationCell<P> CellClass; + typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; // - FmmClassProc algorithm(app.global(),&tree, kernels); + typedef FRotationKernel< CellClass, ContainerClass , P> KernelClass; // - algorithm.execute(); // Here the call of the FMM algorithm + typedef FFmmAlgorithmThreadProc<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClassProc; + + // init oct-tree + OctreeClass tree(TreeHeight, SubTreeHeight, loader->getBoxWidth(), loader->getCenterOfBox()); + + + { // ----------------------------------------------------- + if(app.global().processId() == 0){ + std::cout << "Creating & Inserting " << loader->getNumberOfParticles() + << " particles ..." << std::endl; + std::cout << "\tHeight : " << TreeHeight << " \t sub-height : " << SubTreeHeight << std::endl; + } + time.tic(); + // + + struct TestParticle{ + int indexInFile; + FPoint position; + FReal physicalValue; + const FPoint& getPosition(){ + return position; + } + }; + TestParticle* particles = new TestParticle[loader->getMyNumberOfParticles()]; + memset(particles, 0, (unsigned int) (sizeof(TestParticle) * loader->getMyNumberOfParticles())); + + //idx (in file) of the first part that will be used by this proc. + int idxStart = loader->getStart(); + + for(int idxPart = 0 ; idxPart < loader->getMyNumberOfParticles() ; ++idxPart){ + //Storage of the index (in the original file) of each part. + particles[idxPart].indexInFile = idxPart + idxStart; + + // Read particles from file + loader->fillParticle(&particles[idxPart].position,&particles[idxPart].physicalValue); + } + + FVector<TestParticle> finalParticles; + FLeafBalance 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].indexInFile,finalParticles[idx].physicalValue); + } + + delete[] particles; + + time.tac(); + std::cout << "Done " << "(@Creating and Inserting Particles = " + << time.elapsed() << "s)." << std::endl; + } // ----------------------------------------------------- + + { // ----------------------------------------------------- + std::cout << "\nRotation harmonic Spherical FMM Proc (P="<< P << ") ... " << std::endl; + + time.tic(); + // + // Here we use a pointer due to the limited size of the stack + // + KernelClass *kernels = new KernelClass(TreeHeight, loader->getBoxWidth(), loader->getCenterOfBox()); + // + FmmClassProc algorithm(app.global(),&tree, kernels); + // + algorithm.execute(); // Here the call of the FMM algorithm + // + time.tac(); + std::cout << "Done " << "(@Algorithm = " << time.elapsed() << "s)." << std::endl; + } + // ----------------------------------------------------- // - time.tac(); - std::cout << "Done " << "(@Algorithm = " << time.elapsed() << "s)." << std::endl; - } - // ----------------------------------------------------- - // - // Some output - // - // - - { // ----------------------------------------------------- - long int N1=0, N2= loader->getNumberOfParticles()/2, N3= (loader->getNumberOfParticles()-1); ; - FReal energy =0.0 ; + // Some output // - // Loop over all leaves // - std::cout <<std::endl<<" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "<<std::endl; - std::cout << std::scientific; - std::cout.precision(10) ; - - tree.forEachLeaf([&](LeafClass* leaf){ - const FReal*const posX = leaf->getTargets()->getPositions()[0]; - const FReal*const posY = leaf->getTargets()->getPositions()[1]; - const FReal*const posZ = leaf->getTargets()->getPositions()[2]; - 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(); - const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues(); - - const FVector<int>& indexes = leaf->getTargets()->getIndexes(); - - for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ - const int indexPartOrig = indexes[idxPart]; - if ((indexPartOrig == N1) || (indexPartOrig == N2) || (indexPartOrig == N3) ) { - std::cout << "Proc "<< app.global().processId() << " Index "<< indexPartOrig << " potential " << potentials[idxPart] - << " Pos "<<posX[idxPart]<<" "<<posY[idxPart]<<" "<<posZ[idxPart] - << " Forces: " << forcesX[idxPart] << " " << forcesY[idxPart] << " "<< forcesZ[idxPart] <<std::endl; - } - energy += potentials[idxPart]*physicalValues[idxPart] ; - } - }); - - FReal gloEnergy = app.global().reduceSum(energy); - if(0 == app.global().processId()){ - std::cout <<std::endl << "Proc "<< app.global().processId() << " Energy: "<< gloEnergy <<std::endl; - std::cout <<std::endl <<" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "<<std::endl<<std::endl; + + { // ----------------------------------------------------- + long int N1=0, N2= loader->getNumberOfParticles()/2, N3= (loader->getNumberOfParticles()-1); ; + FReal energy =0.0 ; + // + // Loop over all leaves + // + std::cout <<std::endl<<" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "<<std::endl; + std::cout << std::scientific; + std::cout.precision(10) ; + + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const posX = leaf->getTargets()->getPositions()[0]; + const FReal*const posY = leaf->getTargets()->getPositions()[1]; + const FReal*const posZ = leaf->getTargets()->getPositions()[2]; + 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(); + const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues(); + + const FVector<int>& indexes = leaf->getTargets()->getIndexes(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + const int indexPartOrig = indexes[idxPart]; + if ((indexPartOrig == N1) || (indexPartOrig == N2) || (indexPartOrig == N3) ) { + std::cout << "Proc "<< app.global().processId() << " Index "<< indexPartOrig << " potential " << potentials[idxPart] + << " Pos "<<posX[idxPart]<<" "<<posY[idxPart]<<" "<<posZ[idxPart] + << " Forces: " << forcesX[idxPart] << " " << forcesY[idxPart] << " "<< forcesZ[idxPart] <<std::endl; + } + energy += potentials[idxPart]*physicalValues[idxPart] ; + } + }); + + FReal gloEnergy = app.global().reduceSum(energy); + if(0 == app.global().processId()){ + std::cout <<std::endl << "Proc "<< app.global().processId() << " Energy: "<< gloEnergy <<std::endl; + std::cout <<std::endl <<" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "<<std::endl<<std::endl; + } } - } - delete loader; - // ----------------------------------------------------- - - return 0; + delete loader; + // ----------------------------------------------------- + + return 0; } diff --git a/Examples/changeFmaFormat.cpp b/Examples/changeFmaFormat.cpp index 50f55d28627e787e44c9a7d37c5b456e8bebd5ec..36cf1fece590ac1cfeca9ef6a3724d818fa71b53 100644 --- a/Examples/changeFmaFormat.cpp +++ b/Examples/changeFmaFormat.cpp @@ -18,6 +18,8 @@ #include "Utils/FParameters.hpp" #include "Utils/FGenerateDistribution.hpp" +#include "../Src/Utils/FParameterNames.hpp" + // /// \file changeFmaFormat.cpp //! @@ -43,84 +45,62 @@ //! changeFormat -fin unitCubeXYZQ100.fma -fout unitCubeXYZQ100 -bin -// -// -void genDistusage() { - std::cout << "Driver to change the format of the input file" - << std::endl; - std::cout << "Options "<< std::endl - << " -help to see the parameters " << std::endl - << " Input: only one option is allowed" << std::endl - << " -fin name: file name to convert (with extension .fma (ascii) or bfma (binary) " <<std::endl - << " -fdlpoly name: file name to convert with extension (.bin if binary file) " <<std::endl - << " Output " << std::endl - << " -fout name: generic name for files (without extension) and save data" <<std::endl - << " with following format in name.fma or name.bfma if -bin is set" <<std::endl - << " -bin save output in binary mode (name file name.bfma)" <<std::endl - << " -visufmt vtk, vtp, cosmo or cvs format for visualization " <<std::endl; -} - int main(int argc, char ** argv){ - // - if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")|| (argc < 3 )){ - genDistusage() ; - exit(-1); - } + FHelpDescribeAndExit(argc, argv, + "Driver to change the format of the input file. " + "fdlpoly is not supported for now.", + FParameterDefinitions::InputFile, FParameterDefinitions::OutputFile, + FParameterDefinitions::OutputVisuFile, FParameterDefinitions::OutputBinFormat); + FSize NbPoints; FReal * particles = nullptr ; FFmaGenericLoader * loader; unsigned int nbData; - if (FParameters::existParameter(argc, argv, "-fin")) { - const std::string filename(FParameters::getStr(argc,argv,"-fin", "data.fma")); + const std::string filename(FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "data.fma")); - loader = new FFmaGenericLoader(filename); - // - // Allocation - // - NbPoints = loader->getNumberOfParticles(); - nbData = loader->getNbRecordPerline() ; - const unsigned int arraySize =nbData*NbPoints; - // - particles = new FReal[arraySize] ; - std::memset(particles,0,arraySize*sizeof(FReal)); - // - // Read Data - int j = 0 ; - for(int idxPart = 0 ; idxPart < NbPoints ;++idxPart, j+=nbData){ - // // - loader->fillParticle(&particles[j],nbData); - // std::cout << "idxPart "<< idxPart << " "; - // for (int jj= 0 ; jj<nbData ; ++jj, ++k){ - // std::cout << particles[k] << " "; - // } - // std::cout << std::endl; - } - // if(FParameters::existParameter(argc, argv, "-fdlpoly")){ - // FDlpolyLoader *loader = nullptr ; - // // if(FParameters::existParameter(argc, argv, "-bin")){ - // // loader = new FDlpolyBinLoader(filenameEwaldIn.c_str()); - // // } - // // else { - // // loader = new FDlpolyAsciiLoader(filenameEwaldIn.c_str()); - // // } - // // NbPoints = loader->getNumberOfParticles() ; - // // particles = new FReal[arraySize] ; - // // std::memset(particles,0,arraySize*sizeof(FReal)); - // // for(int idxPart = 0 ; idxPart < NbPoints ; ++idxPart){ - // // - // // int index ; - // // FPoint P ; FReal t[3]; - // /// / loader->fillParticle(&P, t, &physicalValue,&index); - // // particles[(index-1)*] - // // - // // totalCharge += physicalValue ; - // } - } - else { - genDistusage() ; - return 0; + loader = new FFmaGenericLoader(filename); + // + // Allocation + // + NbPoints = loader->getNumberOfParticles(); + nbData = loader->getNbRecordPerline() ; + const unsigned int arraySize =nbData*NbPoints; + // + particles = new FReal[arraySize] ; + std::memset(particles,0,arraySize*sizeof(FReal)); + // + // Read Data + int j = 0 ; + for(int idxPart = 0 ; idxPart < NbPoints ;++idxPart, j+=nbData){ + // // + loader->fillParticle(&particles[j],nbData); + // std::cout << "idxPart "<< idxPart << " "; + // for (int jj= 0 ; jj<nbData ; ++jj, ++k){ + // std::cout << particles[k] << " "; + // } + // std::cout << std::endl; } + // if(FParameters::existParameter(argc, argv, "-fdlpoly")){ + // FDlpolyLoader *loader = nullptr ; + // // if(FParameters::existParameter(argc, argv, "-bin")){ + // // loader = new FDlpolyBinLoader(filenameEwaldIn.c_str()); + // // } + // // else { + // // loader = new FDlpolyAsciiLoader(filenameEwaldIn.c_str()); + // // } + // // NbPoints = loader->getNumberOfParticles() ; + // // particles = new FReal[arraySize] ; + // // std::memset(particles,0,arraySize*sizeof(FReal)); + // // for(int idxPart = 0 ; idxPart < NbPoints ; ++idxPart){ + // // + // // int index ; + // // FPoint P ; FReal t[3]; + // /// / loader->fillParticle(&P, t, &physicalValue,&index); + // // particles[(index-1)*] + // // + // // totalCharge += physicalValue ; + // } // @@ -130,74 +110,74 @@ int main(int argc, char ** argv){ // // Generate file for ScalFMM FMAGenericLoader // - if(FParameters::existParameter(argc, argv, "-fout")){ - std::string name(FParameters::getStr(argc,argv,"-fout", "output")); - std::string ext("."); - if(name.find(ext) !=std::string::npos) { - std::cout << "No file with extension permitted for output name : " << name << std::endl; - exit(-1); - } - if( FParameters::existParameter(argc, argv, "-bin")){ - name += ".bfma"; - } - else { - name += ".fma"; - } - FFmaGenericWriter writer(name) ; - writer.writeHeader( loader->getCenterOfBox(), loader->getBoxWidth() , NbPoints, sizeof(FReal), nbData) ; - writer.writeArrayOfReal(particles, nbData, NbPoints); + if(FParameters::existParameter(argc, argv, FParameterDefinitions::OutputFile.options)){ + std::string name(FParameters::getStr(argc,argv,FParameterDefinitions::OutputFile.options, "output")); + std::string ext("."); + if(name.find(ext) !=std::string::npos) { + std::cout << "No file with extension permitted for output name : " << name << std::endl; + exit(-1); + } + if( FParameters::existParameter(argc, argv, FParameterDefinitions::OutputBinFormat.options)){ + name += ".bfma"; + } + else { + name += ".fma"; + } + FFmaGenericWriter writer(name) ; + writer.writeHeader( loader->getCenterOfBox(), loader->getBoxWidth() , NbPoints, sizeof(FReal), nbData) ; + writer.writeArrayOfReal(particles, nbData, NbPoints); } // // Generate file for visualization purpose // - if(FParameters::existParameter(argc, argv, "-visufmt")){ - std::string outfilename(FParameters::getStr(argc,argv,"-fout", "output")); - std::string visufile(""), fmt(FParameters::getStr(argc,argv,"-visufmt", "vtp")); - if( fmt == "vtp" ){ - visufile = outfilename + ".vtp" ; - } - else if( fmt == "vtk" ){ - visufile = outfilename + ".vtk" ; - } - else if( fmt == "cosmo" ){ - if(nbData !=4) { - std::cerr << "Cosmos export accept only 4 data per particles. here: "<<nbData<<std::endl; - std::exit(EXIT_FAILURE); - } - visufile = outfilename + ".cosmo" ; - } - else { - visufile = outfilename + ".csv" ; - } - std::ofstream file( visufile, std::ofstream::out); - if(!file) { - std::cout << "Cannot open file."<< std::endl; - exit(-1) ; - } // - // - // Export data in cvs format - // - if( fmt == "vtp" ){ - std::cout << "Writes in XML VTP format (visualization) in file "<< visufile <<std::endl ; - if(nbData==4){ - exportVTKxml( file, particles, NbPoints) ; - } - else { - exportVTKxml( file, particles, NbPoints,nbData) ; - } - } - else if( fmt == "vtk" ){ - std::cout << "Writes in VTK format (visualization) in file "<< visufile <<std::endl ; - exportVTK( file, particles, NbPoints,nbData) ; - } - else if( fmt == "cosmo" ){ - std::cout << "Writes in COSMO format (visualization) in file "<< visufile <<std::endl ; - exportCOSMOS( file, particles, NbPoints) ; - } - else { - std::cout << "Writes in CVS format (visualization) in file "<<visufile<<std::endl ; - exportCVS( file, particles, NbPoints,nbData) ; - } + if(FParameters::existParameter(argc, argv, FParameterDefinitions::OutputVisuFile.options)){ + std::string outfilename(FParameters::getStr(argc,argv,FParameterDefinitions::OutputFile.options, "output")); + std::string visufile(""), fmt(FParameters::getStr(argc,argv,FParameterDefinitions::OutputVisuFile.options, "vtp")); + if( fmt == "vtp" ){ + visufile = outfilename + ".vtp" ; + } + else if( fmt == "vtk" ){ + visufile = outfilename + ".vtk" ; + } + else if( fmt == "cosmo" ){ + if(nbData !=4) { + std::cerr << "Cosmos export accept only 4 data per particles. here: "<<nbData<<std::endl; + std::exit(EXIT_FAILURE); + } + visufile = outfilename + ".cosmo" ; + } + else { + visufile = outfilename + ".csv" ; + } + std::ofstream file( visufile, std::ofstream::out); + if(!file) { + std::cout << "Cannot open file."<< std::endl; + exit(-1) ; + } // + // + // Export data in cvs format + // + if( fmt == "vtp" ){ + std::cout << "Writes in XML VTP format (visualization) in file "<< visufile <<std::endl ; + if(nbData==4){ + exportVTKxml( file, particles, NbPoints) ; + } + else { + exportVTKxml( file, particles, NbPoints,nbData) ; + } + } + else if( fmt == "vtk" ){ + std::cout << "Writes in VTK format (visualization) in file "<< visufile <<std::endl ; + exportVTK( file, particles, NbPoints,nbData) ; + } + else if( fmt == "cosmo" ){ + std::cout << "Writes in COSMO format (visualization) in file "<< visufile <<std::endl ; + exportCOSMOS( file, particles, NbPoints) ; + } + else { + std::cout << "Writes in CVS format (visualization) in file "<<visufile<<std::endl ; + exportCVS( file, particles, NbPoints,nbData) ; + } } // delete particles ; diff --git a/Examples/compareAllPoissonKernels.cpp b/Examples/compareAllPoissonKernels.cpp index e2d5713bac26ac3bb2c08c528bcfbeb3c5ba1268..c74ee6814dc8163c9216a2d944a844c6e6df8357 100644 --- a/Examples/compareAllPoissonKernels.cpp +++ b/Examples/compareAllPoissonKernels.cpp @@ -75,6 +75,7 @@ #include "Kernels/Uniform/FUnifKernel.hpp" #endif +#include "../Src/Utils/FParameterNames.hpp" /** * This program compares two different kernels, eg., the Chebyshev kernel with @@ -94,46 +95,24 @@ //! - Chebychev and symetric Chebychev interpolation //! - if FFT is activated: interpolation on uniform grid //!<br> -//! <b> General arguments:</b> -//! \param -depth The depth of the octree -//! \param -subdepth Specifies the size of the sub octree -//! \param -t The number of threads -//! -//! \param -f name Name of the particles file with extension (.fma or .bfma). The data in file have to be in our FMA format -//! -//! -//! \b examples -//! -//! Transform an ascii file in a binary file -//! -//! changeFormat -fin unitCubeXYZQ100.fma -fout unitCubeXYZQ100 -bin - -void usage() { - std::cout << "Driver for testing different approximations for the 1/r kernel" << std::endl; - std::cout << "Options "<< std::endl - << " -help to see the parameters " << std::endl - << " -depth the depth of the octree "<< std::endl - << " -subdepth specifies the size of the sub octree " << std::endl - << " -f name name specifies the name of the particle distribution" << std::endl - << " -t n specifies the number of threads used in the computations" << std::endl; -} + // Simply create particles and try the kernels int main(int argc, char* argv[]) { - if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")){ - usage() ; - std::cout << "Driver for testing different approximations for the 1/r kernel" << std::endl; + FHelpDescribeAndExit(argc, argv, + "Driver for testing different approximations for the 1/r kernel.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::InputFile, + FParameterDefinitions::NbThreads, FParameterDefinitions::SHDevelopment); - exit(EXIT_SUCCESS); - } // get info from commande line - const std::string filename(FParameters::getStr(argc,argv,"-f", "../Data/UTest/unitCubeRef20kDouble.bfma")); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", omp_get_max_threads()); - const int DevP = FParameters::getValue(argc, argv, "-p", 11); + const std::string filename(FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/UTest/unitCubeRef20kDouble.bfma")); + 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 NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, omp_get_max_threads()); + const int DevP = FParameters::getValue(argc, argv, FParameterDefinitions::SHDevelopment.options, 11); // #ifdef _OPENMP diff --git a/Examples/generateDistributions.cpp b/Examples/generateDistributions.cpp index d54bdd38727b54949cc50ef082f45e8232ba2406..6342765f4760ab74bbe3fc2a906c6cd2649086c5 100644 --- a/Examples/generateDistributions.cpp +++ b/Examples/generateDistributions.cpp @@ -17,6 +17,8 @@ #include "Utils/FGenerateDistribution.hpp" #include "Files/FFmaGenericLoader.hpp" +#include "../Src/Utils/FParameterNames.hpp" + // /// \file generateDistributions.cpp //! @@ -68,52 +70,45 @@ //! //! generateDistributions -cuboid 2:2:4 -filename cuboid -visufmt vtp -charge -zeromean //! -// -// -// -void genDistusage() { - std::cout << "Driver to generate N points (non)uniformly distributed on a given geometry" - << std::endl; - std::cout << "Options "<< std::endl - << " -help to see the parameters " << std::endl - << " -N The number of points in the distribution " << std::endl - << " -extraLength value extra length to add to the boxWidth"<< std::endl - << std::endl - << " Distributions " << std::endl - << " Uniform on " << std::endl - << " -unitCube uniform distribution on unit cube" <<std::endl - << " -cuboid uniform distribution on rectangular cuboid of size a:b:c" <<std::endl - << " -lengths a:b:c - default values are 1.0:1.0:2.0" <<std::endl - << " -unitSphere uniform distribution on unit sphere" <<std::endl - << " -sphere uniform distribution on sphere of radius given by" <<std::endl - << " -radius R - default value for R is 2.0" <<std::endl - << " -prolate ellipsoid with aspect ratio a:a:c" <<std::endl - << " -ar a:a:c with c > a > 0" <<std::endl<<std::endl - << " Non Uniform on " << std::endl - << " -ellipsoid non uniform distribution on an ellipsoid of aspect ratio given by" <<std::endl - << " -ar a:b:c with a, b and c > 0" <<std::endl - << " -plummer (Highly non unuiform) plummer distrinution (astrophysics)"<<std::endl - << " -radius R - default value 10.0" <<std::endl - << " Physical values" <<std::endl - << " -charge generate physical values between -1 and 1 otherwise generate between 0 and 1 " <<std::endl<<std::endl - << " -zeromean the average of the physical values is zero " <<std::endl<<std::endl - << " Output " << std::endl - << " -filename name: generic name for files (without extension) and save data" <<std::endl - << " with following format in name.fma or name.bfma in -bin is set" <<std::endl - << " -visufmt vtk, vtp, cosmo or cvs format " <<std::endl; -} int main(int argc, char ** argv){ - // - if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")|| (argc < 3 )){ - genDistusage() ; - exit(-1); - } + FHelpDescribeAndExit(argc, argv, + ">> Driver to generate N points (non)uniformly distributed on a given geometry.\n" + "Options \n" + " -help to see the parameters \n" + " -N The number of points in the distribution \n" + " -extraLength value extra length to add to the boxWidth\n" + " Distributions \n" + " Uniform on \n" + " -unitCube uniform distribution on unit cube\n" + " -cuboid uniform distribution on rectangular cuboid of size a:b:c\n" + " -lengths a:b:c - default values are 1.0:1.0:2.0\n" + " -unitSphere uniform distribution on unit sphere\n" + " -sphere uniform distribution on sphere of radius given by\n" + " -radius R - default value for R is 2.0\n" + " -prolate ellipsoid with aspect ratio a:a:c\n" + " -ar a:a:c with c > a > 0\n" + " Non Uniform on \n" + " -ellipsoid non uniform distribution on an ellipsoid of aspect ratio given by\n" + " -ar a:b:c with a, b and c > 0\n" + " -plummer (Highly non unuiform) plummer distrinution (astrophysics)\n" + " -radius R - default value 10.0\n" + " Physical values\n" + " -charge generate physical values between -1 and 1 otherwise generate between 0 and 1 \n" + " -zeromean the average of the physical values is zero \n" + " Output \n" + " -filename name: generic name for files (without extension) and save data\n" + " with following format in name.fma or name.bfma in -bin is set\n" + " -visufmt vtk, vtp, cosmo or cvs format.", + FParameterDefinitions::InputFile, FParameterDefinitions::NbParticles); + + + FReal extraRadius = 0.000 ; - const int NbPoints = FParameters::getValue(argc,argv,"-N", 20000); - const std::string genericFileName(FParameters::getStr(argc,argv,"-filename", "unifPointDist")); + const int NbPoints = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 20000); + const std::string genericFileName(FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "unifPointDist")); FReal BoxWith = 0.0; FPoint Centre(0.0, 0.0,0.0); // @@ -224,7 +219,7 @@ int main(int argc, char ** argv){ } std::string name(genericFileName); - if( FParameters::existParameter(argc, argv, "-bin")){ + if( FParameters::existParameter(argc, argv, FParameterDefinitions::OutputBinFormat.options)){ name += ".bfma"; } else { @@ -237,8 +232,8 @@ int main(int argc, char ** argv){ // // Generate file for visualization // - if(FParameters::existParameter(argc, argv, "-visufmt")){ - std::string visufile(""), fmt(FParameters::getStr(argc,argv,"-visufmt", "vtp")); + if(FParameters::existParameter(argc, argv, FParameterDefinitions::OutputVisuFile.options)){ + std::string visufile(""), fmt(FParameters::getStr(argc,argv,FParameterDefinitions::OutputVisuFile.options, "vtp")); if( fmt == "vtp" ){ visufile = genericFileName + ".vtp" ; } diff --git a/Examples/statisticsOnOctree.cpp b/Examples/statisticsOnOctree.cpp index b0ca2ea34fba0bce0c531b65178950a520528a34..352939767f4977c5c5f2ab9f6bfabfdcfe2f87b5 100755 --- a/Examples/statisticsOnOctree.cpp +++ b/Examples/statisticsOnOctree.cpp @@ -29,6 +29,7 @@ #include "../../Src/Utils/FMath.hpp" #include "../../Src/Files/FFmaGenericLoader.hpp" +#include "../Src/Utils/FParameterNames.hpp" /// \file statisticsOnOctree.cpp //! @@ -46,52 +47,40 @@ //! //! \arg The number of cells, of adaptive cells (cell with more one child) //! \arg The average, min and max numbers of M2L operators and also its variance. - -//! -//! <b> General arguments:</b> -//! \param -help(-h) to see the parameters available in this driver -//! \param -depth The depth of the octree -//! \param -subdepth Specifies the size of the sub octree -//! -//! \param -infile name Name of the particles file. The file have to be in our FMA format -//! \param -bin if the input file in binary mode -//! \param -outfile name Generic name for output file (without extension) //! //! <b> Statistics options:</b> //! \param -histP build a file to generate histogram of particles per leaf. The data are store in file given by -outfile arguments and .txt extension // Simply create particles and try the kernels // -void usage() { - std::cout << "Driver to obtain statistics on the octree" << std::endl; - std::cout << "Options "<< std::endl - << " -help to see the parameters " << std::endl - << " -depth the depth of the octree "<< std::endl - << " -subdepth specifies the size of the sub octree " << std::endl - << " -infile name specifies the name of the particle distribution" << std::endl - << " -bin if the input file in binary mode"<< std::endl - << " -outfile name specifies the file for the diagnostics" << std::endl - << " -histP build the histogram of the particle number per leaf"<<std::endl; -} + +static const FParameterNames LocalOptitionHist = { + {"-histP", "--histogram-stat"} , + "Build the histogram of the particle number per leaf." +}; int main(int argc, char ** argv){ - typedef FBasicParticleContainer<0> ContainerClass; - typedef FSimpleLeaf< ContainerClass > LeafClass; + FHelpDescribeAndExit(argc, argv, + "Driver to obtain statistics on the octree.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, + FParameterDefinitions::OutputFile, LocalOptitionHist); + + + typedef FBasicParticleContainer<0> ContainerClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; typedef FOctree< FBasicCell, ContainerClass , LeafClass > OctreeClass; - if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")|| (argc < 3 )){ - usage() ; - exit(-1); - } + // // Octree parameters // - const int TreeHeight = FParameters::getValue(argc,argv,"-depth", 5); - const int SubTreeHeight = FParameters::getValue(argc,argv,"-subdepth", 3); + const int TreeHeight = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SubTreeHeight = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); // // input and output Files parameters // - const char* const filename = FParameters::getStr(argc,argv,"-infile", "../Data/test20k.fma"); - const std::string genericFileName(FParameters::getStr(argc,argv,"-outfile", "output")); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); + const std::string genericFileName(FParameters::getStr(argc,argv,FParameterDefinitions::OutputFile.options, "output")); // std::cout << "Parameters "<< std::endl << " Octree Depth "<< TreeHeight <<std::endl @@ -171,7 +160,7 @@ int main(int argc, char ** argv){ // Histogram of particles per leaf // - if(FParameters::existParameter(argc, argv, "-histP")){ + if(FParameters::existParameter(argc, argv, LocalOptitionHist.options)){ int size = maxParticles+1; int * hist = new int [size] ; memset(hist,0,(size)*sizeof(int)); diff --git a/Src/Utils/FParameterNames.hpp b/Src/Utils/FParameterNames.hpp new file mode 100644 index 0000000000000000000000000000000000000000..60f8719b60920a369e1225cf9bc0c0e7324169f4 --- /dev/null +++ b/Src/Utils/FParameterNames.hpp @@ -0,0 +1,202 @@ +// =================================================================================== +// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger 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". +// =================================================================================== +#ifdef FPARAMETERNAMES_HPP +#error FParameterNames must be included only once by each main file! +#else +#define FPARAMETERNAMES_HPP + +#include "../Src/Utils/FGlobal.hpp" + +#include "../Src/Utils/FParameters.hpp" + +#include <iostream> +#include <vector> + +/** + * This file contains some useful classes/functions to manage the parameters, + * but it also contains all the parameters definitions! + * A Scalfmm executable must define a static object to propose a parameter to the user. + */ + +/** A parameter descriptor */ +struct FParameterNames { + std::vector<const char*> options; + const char* description; +}; + +/** The namespace where we put all the definitions */ +namespace FParameterDefinitions { + +static const FParameterNames Help = { + {"-help", "--help"} , + "To have print the options used by the application." +}; + +static const FParameterNames NbParticles = { + {"-nb", "--number-of-particles", "-N"} , + "The number of particles if they are generated by the executable." +}; + +static const FParameterNames OctreeHeight = { + {"-h", "--height", "-depth"} , + "The number of levels in the octree (at least 2 for the root and the leaves)." +}; + +static const FParameterNames OctreeSubHeight = { + {"-sh", "--sub-height", "-subdepth"} , + "The number of allocated levels in the sub octree." +}; + +static const FParameterNames InputFile = { + {"-f", "-fin", "--input-filename", "-filename"} , + "To give an input file." +}; + +static const FParameterNames InputFileOne = { + {"-f1", "-fin1", "--file-one"} , + "To give the first input file." +}; + +static const FParameterNames InputFileTwow = { + {"-f2", "-fin2", "--file-two"} , + "To give the second input file." +}; + +static const FParameterNames InputBinFormat = { + {"-binin", "-bininput", "--binary-input"} , + "To input is in binary format." +}; + +static const FParameterNames OutputFile = { + {"-fout", "--output-filename"} , + "To give the output filename." +}; + +static const FParameterNames OutputVisuFile = { + {"-fvisuout", "-visufmt"} , + "To give the output filename in visu format." +}; + +static const FParameterNames OutputBinFormat = { + {"-binout", "-binoutput"} , + "To output in binary format." +}; + +static const FParameterNames NbThreads = { + {"-t", "-nbthreads"} , + "To choose the number of threads." +}; + +static const FParameterNames SequentialFmm = { + {"-sequential", "--sequential-fmm"} , + "No parallelization in the FMM algorithm." +}; + +static const FParameterNames TaskFmm = { + {"-task", "--task-fmm"} , + "Task parallelization in the FMM algorithm." +}; + +static const FParameterNames SHDevelopment = { + {"-devp", "-sh-p"} , + "The degree of development for the spherical harmonic kernel (P)." +}; + +static const FParameterNames EnabledVerbose = { + {"-verbose", "--verbose"} , + "To have a high degree of verbosity." +}; + +static const FParameterNames PeriodicityNbLevels = { + {"-per", "--periodic-degree"} , + "The number of level upper to the root to proceed." +}; + +static const FParameterNames PeriodicityDisabled = { + {"-noper", "--no-periodicity"} , + "To disable the periodicity." +}; + +static const FParameterNames DeltaT = { + {"-dt", "--delta-time"} , + "The time step between iterations." +}; + +static const FParameterNames RotationKernel = { + {"-rotation", "--rotation-kernel"} , + "To use the rotation kernel (based on spherical harmonics)." +}; + +static const FParameterNames SphericalKernel = { + {"-spherical", "--spherical-kernel"} , + "To use the spherical harmonics old kernel." +}; + +static const FParameterNames ChebyshevKernel = { + {"-chebyshev", "--chebyshev-kernel"} , + "To use the Chebyshev kernel." +}; + +static const FParameterNames Epsilon = { + {"-epsilon", "--epsilon"} , + "The epsilon needed for the application." +}; + +static const FParameterNames PhysicalValue = { + {"-pv", "--physical-value"} , + "The physical value of the particles." +}; + +/** To print a list of parameters */ +inline void PrintUsedOptions(const std::vector<FParameterNames>& options){ + std::cout << ">> Here is the list of the parameters you can pass to this application :\n"; + for(const FParameterNames& option : options ){ + std::cout << ">> Descriptions : " << option.description << "\n"; + std::cout << "\t Params : "; + for(const char* name : option.options ){ + std::cout << name << ", "; + } + std::cout << "\n"; + } +} + +}// End of namespace + +/** This should be include at the beginin of all main file + * @code FHelpAndExit(argc, argv, FParameterDefinitions::NbParticles, FParameterNames OctreeSubHeight ); + */ +#define FHelpAndExit(argc, argv, ...) \ + if(FParameters::existParameter(argc, argv, FParameterDefinitions::Help.options)) {\ + const std::vector<FParameterNames> optionsvec = {__VA_ARGS__};\ + FParameterDefinitions::PrintUsedOptions(optionsvec);\ + return 0;\ + } \ + +/** This should be include at the beginin of all main file + * @code FHelpDescribeAndExit(argc, argv, + * @code "This executable is doing this and this.", + * @code FParameterDefinitions::NbParticles, FParameterNames OctreeSubHeight ); + */ +#define FHelpDescribeAndExit(argc, argv, description, ...) \ + if(FParameters::existParameter(argc, argv, FParameterDefinitions::Help.options)) {\ + std::cout << argv[0] << " : " << description << "\n"; \ + const std::vector<FParameterNames> optionsvec = {__VA_ARGS__};\ + FParameterDefinitions::PrintUsedOptions(optionsvec);\ + return 0;\ + } \ + + +#endif // FPARAMETERNAMES_HPP diff --git a/Src/Utils/FParameters.hpp b/Src/Utils/FParameters.hpp index b3c67e936988c6426d9056274db9f25ca02212a5..866b384edc60cfa0ab966df7f4a3af9057ee4eec 100755 --- a/Src/Utils/FParameters.hpp +++ b/Src/Utils/FParameters.hpp @@ -16,9 +16,13 @@ #ifndef FPARAMETERS_H #define FPARAMETERS_H +#include "FGlobal.hpp" + #include <sstream> #include <iostream> -//#include <cstring> +#include <cstring> + +#include <vector> /** This file proposes some methods * to work with user input parameters. @@ -114,6 +118,61 @@ namespace FParameters{ } return argv[position+1]; } + + + /** To find a parameters from user format char parameters + * + */ + inline int findParameter(const int argc, const char* const * const argv, const std::vector<const char*>& inNames, const bool caseSensible = false){ + for(const char* name : inNames){ + const int res = findParameter(argc, argv, name, caseSensible); + if(res != NotFound){ + return res; + } + } + return NotFound; + } + + /** To know if a parameter exist from user format char parameters + * + */ + inline bool existParameter(const int argc, const char* const * const argv, const std::vector<const char*>& inNames, const bool caseSensible = false){ + for(const char* name : inNames){ + if(existParameter(argc, argv, name, caseSensible)){ + return true; + } + } + return false; + } + + /** To get a value like : + * getValue(argc,argv, "Toto", 0, false); + * will return 55 if the command contains : -Toto 55 + * else 0 + */ + template <class VariableType> + inline const VariableType getValue(const int argc, const char* const * const argv, const std::vector<const char*>& inNames, const VariableType& defaultValue = VariableType(), const bool caseSensible = false){ + for(const char* name : inNames){ + const int position = findParameter(argc, argv, name, caseSensible); + if(position != NotFound && position != argc - 1){ + return StrToOther(argv[position+1],defaultValue); + } + } + return defaultValue; + } + + /** Get a str from argv + */ + inline const char* getStr(const int argc, const char* const * const argv, const std::vector<const char*>& inNames, const char* const inDefault, const bool caseSensible = false){ + for(const char* name : inNames){ + const int position = findParameter(argc, argv, name, caseSensible); + if(position != NotFound && position != argc - 1){ + return argv[position+1]; + } + } + return inDefault; + } + } diff --git a/Tests/Kernels/DirectAlgorithm.cpp b/Tests/Kernels/DirectAlgorithm.cpp index 6f8e88bf2d34907d59103b3b33a26d38c27b65cd..fa7bbc25b0e0ffaa153e983925fb22b02d267e37 100755 --- a/Tests/Kernels/DirectAlgorithm.cpp +++ b/Tests/Kernels/DirectAlgorithm.cpp @@ -30,6 +30,7 @@ #include "../../Src/Utils/FTic.hpp" #include "../../Src/Utils/FMath.hpp" #include "../../Src/Utils/FParameters.hpp" +#include "../../Src/Utils/FParameterNames.hpp" #include "../../Src/Utils/FIOVtk.hpp" #include "../../Src/Containers/FOctree.hpp" @@ -69,8 +70,16 @@ struct MDParticle { // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FP2PParticleContainerIndexed<> ContainerClass; + FHelpDescribeAndExit(argc, argv, + ">> This executable has to be used to compute direct interaction either for periodic or non periodic system.\n" + ">> options are -depth H -subdepth SH [-per perdeep, -noper] -fin filenameIN (-bin) -fout filenameOUT \n" + ">> Recommended files : ../Data/EwalTest_Periodic.run ../Data/EwalTest_NoPeriodic.run.", + FParameterDefinitions::OutputFile, FParameterDefinitions::EnabledVerbose, + FParameterDefinitions::PeriodicityDisabled, FParameterDefinitions::PeriodicityNbLevels, + FParameterDefinitions::OutputFile, FParameterDefinitions::InputFile, + FParameterDefinitions::InputBinFormat); + typedef FP2PParticleContainerIndexed<> ContainerClass; typedef FSimpleLeaf< ContainerClass > LeafClass; typedef FInterpMatrixKernelR MatrixKernelClass; const MatrixKernelClass MatrixKernel; @@ -93,32 +102,13 @@ int main(int argc, char ** argv){ typedef FFmmAlgorithmPeriodic<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; // typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassNoPer; - ///////////////////////What we do///////////////////////////// - if( FParameters::existParameter(argc, argv, "-help")){ - std::cout << ">> This executable has to be used to compute direct interaction either for periodic or non periodic system.\n"; - std::cout << ">> options are -depth H -subdepth SH [-per perdeep, -noper] -fin filenameIN (-bin) -fout filenameOUT \n"; - std::cout << ">> Recommended files : ../Data/EwalTest_Periodic.run ../Data/EwalTest_NoPeriodic.run\n"; - std::cout << " Options " << std::endl; - std::cout <<" -bin if input file is in binary mode "<< std::endl; - std::cout << " -per perDeep " << std::endl; - std::cout << " -noper no periodic boundary conditions " << std::endl; - std::cout << " -verbose : print index x y z fx fy fy Q and V" << std::endl; - std::cout << " -fout filenameOUT binary output file " << std::endl; - std::exit( EXIT_FAILURE); - - } - if(FParameters::existParameter(argc, argv, "-per") &&FParameters::existParameter(argc, argv, "-noper") ){ - std::cerr <<" Error -per X and -noper are forbidden together " << std::endl; - std::exit( EXIT_FAILURE); - } - ////////////////////////////////////////////////////////////// - const int NbLevels = FParameters::getValue(argc,argv,"-depth", 4); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-subdepth", 2); - const int PeriodicDeep = FParameters::getValue(argc,argv,"-per", 3); - const std::string filenameIn(FParameters::getStr(argc,argv,"-fin", "../Data/forceNacl_128_dlpolyPer.bin")); - const char* const filenameOut = FParameters::getStr(argc,argv,"-fout", "periodicDirect.out"); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 4); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 2); + const int PeriodicDeep = FParameters::getValue(argc,argv,FParameterDefinitions::PeriodicityNbLevels.options, 3); + const std::string filenameIn(FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/forceNacl_128_dlpolyPer.bin")); + const char* const filenameOut = FParameters::getStr(argc,argv,FParameterDefinitions::OutputFile.options, "periodicDirect.out"); // file for -saveError option std::ofstream errorfile("outputEwaldError.txt",std::ios::out); @@ -129,7 +119,7 @@ int main(int argc, char ** argv){ // ----------------------------------------------------- std::cout << "Opening : " << filenameIn << "\n"; FDlpolyLoader *loader = nullptr ; - if(FParameters::existParameter(argc, argv, "-bin")){ + if(FParameters::existParameter(argc, argv, FParameterDefinitions::InputBinFormat.options)){ loader = new FDlpolyBinLoader(filenameIn.c_str()); } else { @@ -193,7 +183,7 @@ int main(int argc, char ** argv){ // // --------------------------------------------------------------------------------- FTreeCoordinate min, max; - if( FParameters::existParameter(argc, argv, "-per") ){ + if( FParameters::existParameter(argc, argv, FParameterDefinitions::PeriodicityNbLevels.options) ){ FmmClass algo(&tree,PeriodicDeep); algo.repetitionsIntervals(&min, &max); std::cout << "Simulated box: " << algo.extendedBoxWidth()<<std::endl; @@ -305,7 +295,7 @@ int main(int argc, char ** argv){ std::cout << " Box size: " << loader->getBoxWidth() << " " << sizeof(loader->getBoxWidth())<<std::endl; double boxsize[3] ; boxsize[0] = boxsize[1]= boxsize[2]=loader->getBoxWidth(); int PER[4] ; - if( FParameters::existParameter(argc, argv, "-noper") ){ + if( FParameters::existParameter(argc, argv, FParameterDefinitions::PeriodicityDisabled.options) ){ PER[0] = 0 ; PER[1] = PER[2] = PER[3] = 0 ; } @@ -324,7 +314,7 @@ int main(int argc, char ** argv){ // end generate // ----------------------------------------------------- // - if(FParameters::existParameter(argc, argv, "-verbose")){ + if(FParameters::existParameter(argc, argv, FParameterDefinitions::EnabledVerbose.options)){ denergy = 0 ; for(int idx = 0 ; idx < nbParticles ; ++idx){ std::cout << ">> index " << particlesDirect[idx].index << std::endl; diff --git a/Tests/Kernels/testChebTensorialAlgorithm.cpp b/Tests/Kernels/testChebTensorialAlgorithm.cpp index 2a928c6c32ca560a0aae25ddada77119f3239427..cef220d360a148cd60c9078fa709dcbab02ff41f 100644 --- a/Tests/Kernels/testChebTensorialAlgorithm.cpp +++ b/Tests/Kernels/testChebTensorialAlgorithm.cpp @@ -35,6 +35,7 @@ #include "Kernels/P2P/FP2PParticleContainerIndexed.hpp" #include "Utils/FParameters.hpp" +#include "../../Src/Utils/FParameterNames.hpp" #include "Utils/FMemUtils.hpp" #include "Containers/FOctree.hpp" @@ -50,10 +51,15 @@ // Simply create particles and try the kernels int main(int argc, char* argv[]) { - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 3); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1); + FHelpDescribeAndExit(argc, argv, + "Run the chebyshev FMM kernel and compare the accuracy with a direct computation.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::NbThreads); + + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); + const unsigned int TreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeHeight.options, 3); + const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeSubHeight.options, 2); + const unsigned int NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); #ifdef _OPENMP omp_set_num_threads(NbThreads); @@ -85,8 +91,6 @@ int main(int argc, char* argv[]) FReal potential[NPOT]; }; - const FReal FRandMax = FReal(RAND_MAX); - // open particle file FFmaGenericLoader loader(filename); if(!loader.isOpen()) throw std::runtime_error("Particle file couldn't be opened!"); @@ -103,7 +107,7 @@ int main(int argc, char* argv[]) // Either copy same physical value in each component particles[idxPart].physicalValue[idxPV] = physicalValue; // ... or set random value -// particles[idxPart].physicalValue[idxPV] = physicalValue*FReal(rand())/FRandMax; +// particles[idxPart].physicalValue[idxPV] = physicalValue*FReal(rand())/FReal(RAND_MAX); } for(unsigned idxPot = 0; idxPot<NPOT;++idxPot){ diff --git a/Tests/Kernels/testFlopsChebAlgorithm.cpp b/Tests/Kernels/testFlopsChebAlgorithm.cpp index b3b0c5c6ebc8b3bd1e6b20ba4217ace42fef1cf3..099b5884bee0e3d47ddb7425308771824eef84d3 100755 --- a/Tests/Kernels/testFlopsChebAlgorithm.cpp +++ b/Tests/Kernels/testFlopsChebAlgorithm.cpp @@ -45,14 +45,19 @@ #include "../../Src/Components/FSimpleLeaf.hpp" #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" - +#include "../../Src/Utils/FParameterNames.hpp" int main(int argc, char* argv[]) { - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); + FHelpDescribeAndExit(argc, argv, + "Counts the number of flops requiered for a Chebyshev FMM.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight); + + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); + 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 ORDER = 8; const FReal epsilon = FReal(1e-8); diff --git a/Tests/Kernels/testRotationAlgorithm.cpp b/Tests/Kernels/testRotationAlgorithm.cpp index 7b0df45ab11794910cbdceb4829edf1934815164..09356ecac3c4f656901bd26caeb1277ef4a6a3ed 100755 --- a/Tests/Kernels/testRotationAlgorithm.cpp +++ b/Tests/Kernels/testRotationAlgorithm.cpp @@ -40,8 +40,15 @@ #include "../../Src/Files/FFmaGenericLoader.hpp" +#include "../../Src/Utils/FParameterNames.hpp" int main(int argc, char** argv){ + FHelpDescribeAndExit(argc, argv, + "Run a Spherical Harmonic (Rotation) FMM kernel and compare the accuracy with a direct computation.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::SequentialFmm, + FParameterDefinitions::TaskFmm); + static const int P = 9; typedef FRotationCell<P> CellClass; @@ -58,10 +65,10 @@ int main(int argc, char** argv){ std::cout << ">> This executable has to be used to test Spherical algorithm.\n"; std::cout << ">> You can pass -sequential or -task (thread by default).\n"; ////////////////////////////////////////////////////////////// - const int NbLevels = FParameters::getValue(argc,argv,"-depth", 5); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-subdepth", 3); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); FTic counter; - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; @@ -105,12 +112,12 @@ int main(int argc, char** argv){ std::cout << "Working on particles ..." << std::endl; - if( FParameters::findParameter(argc,argv,"-sequential") != FParameters::NotFound){ + if( FParameters::findParameter(argc,argv,FParameterDefinitions::SequentialFmm.options) != FParameters::NotFound){ FmmClass algo(&tree,&kernels); counter.tic(); algo.execute(); } - else if( FParameters::findParameter(argc,argv,"-task") != FParameters::NotFound){ + else if( FParameters::findParameter(argc,argv,FParameterDefinitions::TaskFmm.options) != FParameters::NotFound){ FmmClassTask algo(&tree,&kernels); counter.tic(); algo.execute(); diff --git a/Tests/Kernels/testRotationPeriodicBench.cpp b/Tests/Kernels/testRotationPeriodicBench.cpp index 4dffefbab5731e2429b82ddbc30e3f25f72cac6b..a89621059ca1b4c2aa26b79e467abdbe51ddcfa8 100644 --- a/Tests/Kernels/testRotationPeriodicBench.cpp +++ b/Tests/Kernels/testRotationPeriodicBench.cpp @@ -31,9 +31,32 @@ #include "../../Src/Utils/FParameters.hpp" #include "../../Src/Utils/FMath.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + +static const FParameterNames LocalOptionMinPer { + {"-min"}, + "The starting periodicity" +}; + +static const FParameterNames LocalOptionMaxPer { + {"-max"}, + "The ending periodicity" +}; + +static const FParameterNames LocalOptionNbPrint { + {"-nbprint"}, + "Number of result to print" +}; int main(int argc, char** argv){ + FHelpDescribeAndExit(argc, argv, + "Run a Spherical Harmonic (Rotation) FMM kernel in periodic.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight,LocalOptionMinPer, + LocalOptionMaxPer, LocalOptionNbPrint + ); + ///////////////////////////////////////////////// // Types ///////////////////////////////////////////////// @@ -52,11 +75,11 @@ int main(int argc, char** argv){ // Parameters const int NbLevels = 4; const int SizeSubLevels = 2; - const int MinLevelAbove = FParameters::getValue(argc, argv, "-min",-1); - const int MaxLevelAbove = FParameters::getValue(argc, argv, "-max",3); + const int MinLevelAbove = FParameters::getValue(argc, argv, LocalOptionMinPer.options,-1); + const int MaxLevelAbove = FParameters::getValue(argc, argv, LocalOptionMaxPer.options,3); const int IncLevelAbove = 1; - const int NbParticles = FParameters::getValue(argc, argv, "-nb",6); - const int NbParticlesPrint = FParameters::getValue(argc, argv, "-nbprint", FMath::Min(6, NbParticles)); + const int NbParticles = FParameters::getValue(argc, argv, FParameterDefinitions::NbParticles.options,6); + const int NbParticlesPrint = FParameters::getValue(argc, argv, LocalOptionNbPrint.options, FMath::Min(6, NbParticles)); FAssertLF(NbParticlesPrint <= NbParticles , "The number of printer particles cannot be higer than the number of particles."); std::cout << "The application will use " << NbParticles << " but studies only " << NbParticlesPrint << " of them." << std::endl; diff --git a/Tests/Kernels/testSphericalAlgorithm.cpp b/Tests/Kernels/testSphericalAlgorithm.cpp index 0b39a4ce8c51d2f1a9d5623cf44777eb9ddd62f8..c773e93dc1891a737236d095614cf74ebc494cfd 100755 --- a/Tests/Kernels/testSphericalAlgorithm.cpp +++ b/Tests/Kernels/testSphericalAlgorithm.cpp @@ -36,6 +36,8 @@ #include "../../Src/Files/FFmaGenericLoader.hpp" #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that each particles is little or longer @@ -45,6 +47,12 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Run a Spherical Harmonic (Old Implementation) FMM kernel and compare the accuracy with a direct computation.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::SequentialFmm, + FParameterDefinitions::TaskFmm); + typedef FSphericalCell CellClass; typedef FP2PParticleContainer<> ContainerClass; @@ -59,11 +67,11 @@ int main(int argc, char ** argv){ std::cout << ">> This executable has to be used to test Spherical algorithm.\n"; std::cout << ">> You can pass -sequential or -task (thread by default).\n"; ////////////////////////////////////////////////////////////// - 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); + const int DevP = FParameters::getValue(argc,argv,FParameterDefinitions::SHDevelopment.options, 8); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); FTic counter; - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; @@ -107,12 +115,12 @@ int main(int argc, char ** argv){ std::cout << "Working on particles ..." << std::endl; - if( FParameters::findParameter(argc,argv,"-sequential") != FParameters::NotFound){ + if( FParameters::findParameter(argc,argv,FParameterDefinitions::SequentialFmm.options) != FParameters::NotFound){ FmmClass algo(&tree,&kernels); counter.tic(); algo.execute(); } - else if( FParameters::findParameter(argc,argv,"-task") != FParameters::NotFound){ + else if( FParameters::findParameter(argc,argv,FParameterDefinitions::TaskFmm.options) != FParameters::NotFound){ FmmClassTask algo(&tree,&kernels); counter.tic(); algo.execute(); diff --git a/Tests/Kernels/testSphericalBench.cpp b/Tests/Kernels/testSphericalBench.cpp index ed89ff39d16b7882e63764d67b179440bbf6d10f..f494bf9349fb70dae1f0e17e2e07c986bb4fcb5b 100755 --- a/Tests/Kernels/testSphericalBench.cpp +++ b/Tests/Kernels/testSphericalBench.cpp @@ -36,6 +36,8 @@ #include "../../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp" #include "../../Src/Kernels/Interpolation/FInterpMatrixKernel.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that each particles is little or longer @@ -193,6 +195,7 @@ void doATest(const int NbParticles, const int minP, const int maxP, const int mi // Simply create particles and try the kernels int main(int argc, char ** argv){ + ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test Spherical algorithm.\n"; std::cout << ">> You can pass -help to know more\n"; @@ -212,14 +215,16 @@ int main(int argc, char ** argv){ std::cout << ">> -test-p [-p P] [-h H] [-nb NB PART] [-pv PHYSICAL VALUE]\n"; std::cout << "To test the time for a run of different nb particles\n\n"; + + FHelpDescribeAndExit(argc, argv, "Please read the code to know more, sorry"); } - const int NbParticles = FParameters::getValue(argc,argv,"-nb", 60000); - const int NbLevels = FParameters::getValue(argc,argv,"-depth", 6); - const int DevP = FParameters::getValue(argc,argv,"-p", 30); + const int NbParticles = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 60000); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 6); + const int DevP = FParameters::getValue(argc,argv,FParameterDefinitions::SHDevelopment.options, 30); const FReal physicalValue = FParameters::getValue(argc,argv,"-pv", 1.0); const bool neutral = FParameters::existParameter(argc,argv,"-neutral"); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-subdepth", 3); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); if( FParameters::existParameter(argc,argv,"-test-hp") ){ std::cout << "Execute : test-hp\n"; diff --git a/Tests/Kernels/testSphericalBlasAlgorithm.cpp b/Tests/Kernels/testSphericalBlasAlgorithm.cpp index c4b729e6315c3e28cf1d8c94aa4190bebe1d5e40..5824f82dd87af84fb0750a6512abd27e0cf239f5 100755 --- a/Tests/Kernels/testSphericalBlasAlgorithm.cpp +++ b/Tests/Kernels/testSphericalBlasAlgorithm.cpp @@ -42,6 +42,8 @@ #include "../../Src/Files/FFmaScanfLoader.hpp" #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** This program show an example of use of * the fmm blas algo * it also check that eachh particles is little or longer @@ -51,6 +53,12 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Run a Spherical Harmonic (BLAS Implementation) FMM kernel and compare the accuracy with a direct computation.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::SequentialFmm, + FParameterDefinitions::TaskFmm, FParameterDefinitions::SHDevelopment); + typedef FSphericalCell CellClass; typedef FP2PParticleContainer<> ContainerClass; @@ -65,12 +73,12 @@ int main(int argc, char ** argv){ std::cout << ">> This executable has to be used to test Spherical Blas algorithm.\n"; std::cout << ">> You can pass -sequential or -task (thread by default).\n"; ////////////////////////////////////////////////////////////// - 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); + const int DevP = FParameters::getValue(argc,argv,FParameterDefinitions::SHDevelopment.options, 8); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); FTic counter; - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; FFmaScanfLoader loader(filename); @@ -113,12 +121,12 @@ int main(int argc, char ** argv){ std::cout << "Working on particles ..." << std::endl; - if( FParameters::findParameter(argc,argv,"-sequential") != FParameters::NotFound){ + if( FParameters::findParameter(argc,argv,FParameterDefinitions::SequentialFmm.options) != FParameters::NotFound){ FmmClass algo(&tree,&kernels); counter.tic(); algo.execute(); } - else if( FParameters::findParameter(argc,argv,"-task") != FParameters::NotFound){ + else if( FParameters::findParameter(argc,argv,FParameterDefinitions::TaskFmm.options) != FParameters::NotFound){ FmmClassTask algo(&tree,&kernels); counter.tic(); algo.execute(); diff --git a/Tests/Kernels/testSphericalBlockBlasAlgorithm.cpp b/Tests/Kernels/testSphericalBlockBlasAlgorithm.cpp index acc0a43a3e8a21739772a10ddd67a60973e0e6d9..252dadac632364ea88ac61fa0293562ab11ed1aa 100755 --- a/Tests/Kernels/testSphericalBlockBlasAlgorithm.cpp +++ b/Tests/Kernels/testSphericalBlockBlasAlgorithm.cpp @@ -43,6 +43,8 @@ #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that eachh particles is little or longer @@ -53,6 +55,12 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Run a Spherical Harmonic (Block BLAS Implementation) FMM kernel and compare the accuracy with a direct computation.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::SequentialFmm, + FParameterDefinitions::TaskFmm, FParameterDefinitions::SHDevelopment); + typedef FSphericalCell CellClass; typedef FP2PParticleContainer<> ContainerClass; @@ -67,12 +75,12 @@ int main(int argc, char ** argv){ std::cout << ">> This executable has to be used to test Spherical Block Blas algorithm.\n"; std::cout << ">> You can pass -sequential or -task (thread by default).\n"; ////////////////////////////////////////////////////////////// - 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); + const int DevP = FParameters::getValue(argc,argv,FParameterDefinitions::SHDevelopment.options, 8); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); FTic counter; - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; FFmaScanfLoader loader(filename); @@ -115,12 +123,12 @@ int main(int argc, char ** argv){ std::cout << "Working on particles ..." << std::endl; - if( FParameters::findParameter(argc,argv,"-sequential") != FParameters::NotFound){ + if( FParameters::findParameter(argc,argv,FParameterDefinitions::SequentialFmm.options) != FParameters::NotFound){ FmmClass algo(&tree,&kernels); counter.tic(); algo.execute(); } - else if( FParameters::findParameter(argc,argv,"-task") != FParameters::NotFound){ + else if( FParameters::findParameter(argc,argv,FParameterDefinitions::TaskFmm.options) != FParameters::NotFound){ FmmClassTask algo(&tree,&kernels); counter.tic(); algo.execute(); diff --git a/Tests/Kernels/testSphericalDlpolyAlgorithm.cpp b/Tests/Kernels/testSphericalDlpolyAlgorithm.cpp index 0fb827b547dea8d9538c6a3fee6f5992a406f941..ab3be8773a7c82b7c1b92a1d6ebc28ebb4b01be1 100755 --- a/Tests/Kernels/testSphericalDlpolyAlgorithm.cpp +++ b/Tests/Kernels/testSphericalDlpolyAlgorithm.cpp @@ -52,6 +52,8 @@ #include "../../Src/Kernels/Chebyshev/FChebSymKernel.hpp" #endif +#include "../../Src/Utils/FParameterNames.hpp" + /** Ewal particle is used in the gadget program * here we try to make the same simulation */ @@ -66,6 +68,7 @@ struct EwalParticle { // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, "Please read the code to know more, sorry"); typedef FP2PParticleContainerIndexed<> ContainerClass; typedef FSimpleLeaf< ContainerClass > LeafClass; @@ -103,10 +106,10 @@ int main(int argc, char ** argv){ } ////////////////////////////////////////////////////////////// - const int NbLevels = FParameters::getValue(argc,argv,"-depth", 4); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-subdepth", 2); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 4); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 2); const int PeriodicDeep = FParameters::getValue(argc,argv,"-per", 3); - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/EwalTest_Periodic.run"); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/EwalTest_Periodic.run"); // file for -saveError option std::ofstream errorfile("outputEwaldError.txt",std::ios::out); @@ -359,7 +362,7 @@ int main(int argc, char ** argv){ part.forces[1] *= scaleForce ; part.forces[2] *= scaleForce ; } - if(FParameters::existParameter(argc, argv, "-verbose")){ + if(FParameters::existParameter(argc, argv, FParameterDefinitions::EnabledVerbose.options)){ std::cout << ">> index " << particles[idxTarget].index << std::endl; std::cout << "Good x " << particles[idxTarget].position.getX() << " y " << particles[idxTarget].position.getY() << " z " << particles[idxTarget].position.getZ() << std::endl; std::cout << "Good fx " <<particles[idxTarget].forces[0] << " fy " << particles[idxTarget].forces[1] << " fz " << particles[idxTarget].forces[2] << std::endl; @@ -464,7 +467,7 @@ int main(int argc, char ** argv){ } energy += potentials[idxPart]*physicalValues[idxPart]; // - if(FParameters::existParameter(argc, argv, "-verbose")){ + if(FParameters::existParameter(argc, argv, FParameterDefinitions::EnabledVerbose.options)){ std::cout << ">> index " << particles[indexPartOrig].index << std::endl; std::cout << "Good x " << particles[indexPartOrig].position.getX() << " y " << particles[indexPartOrig].position.getY() << " z " << particles[indexPartOrig].position.getZ() << std::endl; std::cout << std::fixed << std::setprecision(5) ; diff --git a/Tests/Kernels/testSphericalGalaxyCsv.cpp b/Tests/Kernels/testSphericalGalaxyCsv.cpp index 82ebe3cec7df05d11fea99f8ef9c4f9bb1eecce0..7bf7d20f6a53edf603f36624a5f73657688ce9da 100755 --- a/Tests/Kernels/testSphericalGalaxyCsv.cpp +++ b/Tests/Kernels/testSphericalGalaxyCsv.cpp @@ -39,6 +39,7 @@ #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" class VelocityContainer : public FP2PParticleContainer<> { typedef FP2PParticleContainer<> Parent; @@ -130,6 +131,12 @@ public: // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Run a Spherical Harmonic (Old Implementation) FMM kernel with several time step.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::SHDevelopment, + FParameterDefinitions::DeltaT, FParameterDefinitions::OutputFile); + typedef FSphericalCell CellClass; typedef VelocityContainer ContainerClass; @@ -142,14 +149,14 @@ int main(int argc, char ** argv){ std::cout << ">> This executable has to be used to test Spherical algorithm.\n"; ////////////////////////////////////////////////////////////// - const int NbLevels = FParameters::getValue(argc,argv,"-depth", 6); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-subdepth", 3); - const FReal DT = FParameters::getValue(argc,argv,"-dt", FReal(0.1)); - const int DevP = FParameters::getValue(argc,argv,"-p", 5); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 6); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); + const FReal DT = FParameters::getValue(argc,argv,FParameterDefinitions::DeltaT.options, FReal(0.1)); + const int DevP = FParameters::getValue(argc,argv,FParameterDefinitions::SHDevelopment.options, 5); FSphericalCell::Init(DevP); - GalaxyLoader loader(FParameters::getStr(argc,argv,"-f", "../Data/galaxy.fma.tmp")); + GalaxyLoader loader(FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/galaxy.fma.tmp")); // ----------------------------------------------------- @@ -175,7 +182,7 @@ int main(int argc, char ** argv){ KernelClass kernels( DevP, NbLevels, loader.getBoxWidth(), loader.getCenterOfBox()); FmmClass algo( &tree, &kernels); FOctreeArranger<OctreeClass, ContainerClass, TestParticle, Converter<TestParticle> > arranger(&tree); - FTreeCsvSaver<OctreeClass, ContainerClass> saver("./out/test%d.csv"); + FTreeCsvSaver<OctreeClass, ContainerClass> saver(FParameters::getStr(argc,argv,FParameterDefinitions::OutputFile.options, "/tmp/test%d.csv")); for(int idx = 0; idx < 100 ; ++idx){ algo.execute(); diff --git a/Tests/Kernels/testSphericalProcAlgorithm.cpp b/Tests/Kernels/testSphericalProcAlgorithm.cpp index abce40c516f4861e06b9dd920eff90ded3af642b..cdbef3bfc0beabad028fdef798a1504ce5f56942 100755 --- a/Tests/Kernels/testSphericalProcAlgorithm.cpp +++ b/Tests/Kernels/testSphericalProcAlgorithm.cpp @@ -43,6 +43,8 @@ #include "../../Src/BalanceTree/FLeafBalance.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + #include <iostream> #include <cstdio> @@ -172,8 +174,8 @@ void ValidateFMMAlgoProc(OctreeClass* const badTree, int idxValideLeaf = 0; for(; idxValideLeaf < valideLeaf->getNbParticles() ; ++idxValideLeaf){ if( FMath::LookEqual(validePositionX[idxValideLeaf],positionX[idxLeaf]) && - FMath::LookEqual(validePositionY[idxValideLeaf],positionY[idxLeaf]) && - FMath::LookEqual(validePositionZ[idxValideLeaf],positionZ[idxLeaf]) ){ + FMath::LookEqual(validePositionY[idxValideLeaf],positionY[idxLeaf]) && + FMath::LookEqual(validePositionZ[idxValideLeaf],positionZ[idxLeaf]) ){ break; } } @@ -190,8 +192,8 @@ void ValidateFMMAlgoProc(OctreeClass* const badTree, || FMath::RelatifDiff(valideForcesY[idxValideLeaf],forcesY[idxLeaf]) > Epsilon || FMath::RelatifDiff(valideForcesZ[idxValideLeaf],forcesZ[idxLeaf]) > Epsilon){ std::cout << " Forces error : x " << valideForcesX[idxValideLeaf] << " " << forcesX[idxLeaf] - << " y " << valideForcesY[idxValideLeaf] << " " << forcesY[idxLeaf] - << " z " << valideForcesZ[idxValideLeaf] << " " << forcesZ[idxLeaf] << "\n"; + << " y " << valideForcesY[idxValideLeaf] << " " << forcesY[idxLeaf] + << " z " << valideForcesZ[idxValideLeaf] << " " << forcesZ[idxLeaf] << "\n"; error = true; } if( error ){ @@ -214,211 +216,217 @@ void ValidateFMMAlgoProc(OctreeClass* const badTree, // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FSphericalCell CellClass; - typedef FP2PParticleContainer<> ContainerClass; + FHelpDescribeAndExit(argc, argv, + "Run a Spherical Harmonic (Old Implementation) FMM kernel with mpir parallelization.\n" + "The input file should be in binary format to enable distributed access.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::SHDevelopment); + + typedef FSphericalCell CellClass; + typedef FP2PParticleContainer<> ContainerClass; - typedef FSimpleLeaf< ContainerClass > LeafClass; - typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FSphericalKernel< CellClass, ContainerClass > KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSphericalKernel< CellClass, ContainerClass > KernelClass; - typedef FFmmAlgorithmThreadProc<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassNoProc; + 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"; - ////////////////////////////////////////////////////////////// + ///////////////////////What we do///////////////////////////// + std::cout << ">> This executable has to be used to test Spherical algorithm.\n"; + ////////////////////////////////////////////////////////////// - FMpi app( argc, argv); + 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 DevP = FParameters::getValue(argc,argv,FParameterDefinitions::SHDevelopment.options, 8); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 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,FParameterDefinitions::InputFile.options, defaultFilename); - std::cout << "Opening : " << filename << "\n"; + std::cout << "Opening : " << filename << "\n"; + + FMpiFmaGenericLoader loader(filename, app.global()); + if(!loader.isOpen()){ + std::cout << "Loader Error, " << filename << " is missing\n"; + return 1; + } - FMpiFmaGenericLoader loader(filename, app.global()); - if(!loader.isOpen()){ - std::cout << "Loader Error, " << filename << " is missing\n"; - return 1; - } + CellClass::Init(DevP); - CellClass::Init(DevP); - - - OctreeClass tree(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); - // ----------------------------------------------------- + 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; + std::cout << "Creating & Inserting " << loader.getNumberOfParticles() << " particles ..." << std::endl; + std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - struct TestParticle{ - FPoint position; - FReal physicalValue; - const FPoint& getPosition(){ - return position; - } - }; + 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()); + 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); - } + 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); + 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; + 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 " << "(" << 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; + counter.tac(); + std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; - // ----------------------------------------------------- - std::cout << "Create kernel..." << std::endl; + // ----------------------------------------------------- + std::cout << "Create kernel..." << std::endl; - KernelClass kernels(DevP, NbLevels,loader.getBoxWidth(), loader.getCenterOfBox()); + KernelClass kernels(DevP, NbLevels,loader.getBoxWidth(), loader.getCenterOfBox()); - std::cout << "Done " << " in " << counter.elapsed() << "s)." << std::endl; + std::cout << "Done " << " in " << counter.elapsed() << "s)." << std::endl; - // ----------------------------------------------------- + // ----------------------------------------------------- - std::cout << "Working on particles ..." << std::endl; + std::cout << "Working on particles ..." << std::endl; - FmmClass algo(app.global(),&tree,&kernels); + FmmClass algo(app.global(),&tree,&kernels); - counter.tic(); - algo.execute(); - counter.tac(); + counter.tic(); + algo.execute(); + counter.tac(); - std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl; + std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl; - { // get sum forces&potential + { // get sum forces&potential - FReal potential = 0; - FReal fx = 0.0, fy = 0.0, fz = 0.0; + 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(); + 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]; - } - }); + 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; + 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); + 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; + if(app.global().processId() == 0){ + std::cout << "Foces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; + std::cout << "Potential Sum = " << potential << std::endl; + } } - } #ifdef VALIDATE_FMM - { - OctreeClass treeValide(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); { - FFmaGenericLoader loaderSeq(filename); - FPoint position; - FReal physicalValue; - for(FSize idxPart = 0 ; idxPart < loaderSeq.getNumberOfParticles() ; ++idxPart){ - loaderSeq.fillParticle(&position,&physicalValue); - treeValide.insert(position,physicalValue); - } + OctreeClass treeValide(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); + { + FFmaGenericLoader loaderSeq(filename); + FPoint position; + FReal physicalValue; + for(FSize idxPart = 0 ; idxPart < loaderSeq.getNumberOfParticles() ; ++idxPart){ + loaderSeq.fillParticle(&position,&physicalValue); + treeValide.insert(position,physicalValue); + } + } + + std::cout << "Working on particles ..." << std::endl; + FmmClassNoProc algoValide(&treeValide,&kernels); + counter.tic(); + algoValide.execute(); + counter.tac(); + std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl; + + 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 << "Foces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; + std::cout << "Potential = " << potential << std::endl; + + ValidateFMMAlgoProc<OctreeClass,ContainerClass>(&tree,&treeValide); } - - std::cout << "Working on particles ..." << std::endl; - FmmClassNoProc algoValide(&treeValide,&kernels); - counter.tic(); - algoValide.execute(); - counter.tac(); - std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl; - - 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 << "Foces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; - std::cout << "Potential = " << potential << std::endl; - - ValidateFMMAlgoProc<OctreeClass,ContainerClass>(&tree,&treeValide); - } #endif - // ----------------------------------------------------- + // ----------------------------------------------------- - return 0; + return 0; } diff --git a/Tests/Kernels/testSphericalRotationAlgorithm.cpp b/Tests/Kernels/testSphericalRotationAlgorithm.cpp index 31994ea0b40229411da5f31fe93c43a3fdc09861..414600bbadece0e6aa0054aef0d52beda1e0f5aa 100755 --- a/Tests/Kernels/testSphericalRotationAlgorithm.cpp +++ b/Tests/Kernels/testSphericalRotationAlgorithm.cpp @@ -38,6 +38,8 @@ #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that each particles is little or longer @@ -47,6 +49,12 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Run a Spherical Harmonic (Rotation Old Implementation) FMM kernel and compare the accuracy with a direct computation.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::SequentialFmm, + FParameterDefinitions::TaskFmm, FParameterDefinitions::SHDevelopment); + typedef FSphericalCell CellClass; typedef FP2PParticleContainer<> ContainerClass; @@ -61,12 +69,12 @@ int main(int argc, char ** argv){ std::cout << ">> This executable has to be used to test Spherical Rotation algorithm.\n"; std::cout << ">> You can pass -sequential or -task (thread by default).\n"; ////////////////////////////////////////////////////////////// - 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); + const int DevP = FParameters::getValue(argc,argv,FParameterDefinitions::SHDevelopment.options, 8); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); FTic counter; - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; FFmaScanfLoader loader(filename); @@ -109,12 +117,12 @@ int main(int argc, char ** argv){ std::cout << "Working on particles ..." << std::endl; - if( FParameters::findParameter(argc,argv,"-sequential") != FParameters::NotFound){ + if( FParameters::findParameter(argc,argv,FParameterDefinitions::SequentialFmm.options) != FParameters::NotFound){ FmmClass algo(&tree,&kernels); counter.tic(); algo.execute(); } - else if( FParameters::findParameter(argc,argv,"-task") != FParameters::NotFound){ + else if( FParameters::findParameter(argc,argv,FParameterDefinitions::TaskFmm.options) != FParameters::NotFound){ FmmClassTask algo(&tree,&kernels); counter.tic(); algo.execute(); diff --git a/Tests/Kernels/testTaylor.cpp b/Tests/Kernels/testTaylor.cpp index 49a7304f4f3ca089932d9901456febac71ab9163..e50b3aa16fe9640767afbdf6bd2984eced02e57a 100644 --- a/Tests/Kernels/testTaylor.cpp +++ b/Tests/Kernels/testTaylor.cpp @@ -34,7 +34,7 @@ #include "../../Src/Core/FFmmAlgorithm.hpp" #include "../../Src/Core/FFmmAlgorithmThread.hpp" - +#include "../../Src/Utils/FParameterNames.hpp" // // taylor kernel #include "../../Src/Kernels/Taylor/FTaylorCell.hpp" @@ -53,11 +53,16 @@ // Simply create particles and try the kernels int main(int argc, char* argv[]) { + FHelpDescribeAndExit(argc, argv, + "Run a Taylor FMM kernel and compare the accuracy with a direct computation.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::NbThreads); + // get info from commandline - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", omp_get_max_threads()); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); + 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 NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, omp_get_max_threads()); #ifdef _OPENMP omp_set_num_threads(NbThreads); std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; diff --git a/Tests/Kernels/testTaylorKernel.cpp b/Tests/Kernels/testTaylorKernel.cpp index 158b77a9a6097cbc2f803625b24db3963981df26..0882a8e806ef1b822105876eb3994ee937ff9500 100644 --- a/Tests/Kernels/testTaylorKernel.cpp +++ b/Tests/Kernels/testTaylorKernel.cpp @@ -33,20 +33,22 @@ #include "../../Src/Core/FFmmAlgorithm.hpp" #include "../../Src/Core/FFmmAlgorithmThread.hpp" #include "../../Src/Core/FFmmAlgorithmTask.hpp" +#include "../../Src/Utils/FParameterNames.hpp" +int main(int argc,char** argv){ + FHelpDescribeAndExit(argc, argv, + "Compile a Taylor Kernel (but do nothing)."); + const int P = 10; + const int order = 1; + FPoint centerBox = FPoint(0,0,0); -int main(int /*argc*/,char** /*argv[]*/){ -const int P = 10; -const int order = 1; -FPoint centerBox = FPoint(0,0,0); + typedef FTaylorCell<P,order> CellClass; + typedef FP2PParticleContainer<> ContainerClass; + typedef FTaylorKernel<CellClass,ContainerClass,P,order> KernelClass; + //typedef FSimpleLeaf< ContainerClass > LeafClass; + //typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; -typedef FTaylorCell<P,order> CellClass; - typedef FP2PParticleContainer<> ContainerClass; -typedef FTaylorKernel<CellClass,ContainerClass,P,order> KernelClass; -//typedef FSimpleLeaf< ContainerClass > LeafClass; -//typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + KernelClass kernel(9,1.0,centerBox); -KernelClass kernel(9,1.0,centerBox); - -return 0; + return 0; } diff --git a/Tests/Kernels/testTaylorSimple.cpp b/Tests/Kernels/testTaylorSimple.cpp index 2db8da6b71e737bd9a23e359b3cf77ed3d2964bd..26e2c7caa18b2296630d8c7de317a9f6cf9e0aaf 100644 --- a/Tests/Kernels/testTaylorSimple.cpp +++ b/Tests/Kernels/testTaylorSimple.cpp @@ -16,155 +16,154 @@ #include "../../Src/Containers/FOctree.hpp" #include "../../Src/Core/FFmmAlgorithm.hpp" -//#include "../../Src/Core/FFmmAlgorithmThread.hpp" -//#include "../../Src/Core/FFmmAlgorithmTask.hpp" #include "../../Src/Kernels/Taylor/FTaylorCell.hpp" #include "../../Src/Kernels/Taylor/FTaylorKernel.hpp" +#include "../../Src/Utils/FParameterNames.hpp" -//#include "../../Src/Files/FFmaGenericLoader.hpp" +int main(int argc,char* argv[]){ + FHelpDescribeAndExit(argc, argv, + "Run a Taylor FMM kernel and compare the accuracy with a direct computation.\n" + "The positions of the particles is special.", + FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight); - int main(int argc,char* argv[]){ - const int P = 3; - const int NbLevels = FParameters::getValue(argc, argv, "-depth", 4); - const int SizeSubLevels = FParameters::getValue(argc, argv, "-subdepth", 2); - static const int order = 1; - FPoint rootCenter(FReal(0.0),FReal(0.0),FReal(0.0)); - FReal boxWidth = FReal(4); + const int P = 3; + const int NbLevels = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeHeight.options, 4); + const int SizeSubLevels = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeSubHeight.options, 2); + static const int order = 1; + FPoint rootCenter(FReal(0.0),FReal(0.0),FReal(0.0)); + FReal boxWidth = FReal(4); - typedef FTaylorCell<P,order> CellClass; - typedef FP2PParticleContainer<> ContainerClass; + typedef FTaylorCell<P,order> CellClass; + typedef FP2PParticleContainer<> ContainerClass; - typedef FSimpleLeaf< ContainerClass > LeafClass; - typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FTaylorKernel<CellClass,ContainerClass,P,order> KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FTaylorKernel<CellClass,ContainerClass,P,order> KernelClass; - typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; -// typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassThread; - // typedef FFmmAlgorithmTask<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassTask; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - FTic counter; + OctreeClass tree(NbLevels, SizeSubLevels, boxWidth, rootCenter); - OctreeClass tree(NbLevels, SizeSubLevels, boxWidth, rootCenter); + int nbPart = 3; - int nbPart = 3; - - FPoint tabPart[3]; - tabPart[0] = FPoint(FReal(-1.9),FReal(-1.9),FReal(1.6)); - tabPart[1] = FPoint(FReal(0.9),FReal(1.1),FReal(1.6)); - tabPart[2] = FPoint(FReal(1.9),FReal(0.1),FReal(1.6)); - //tabPart[2] = FPoint(FReal(0.1),FReal(1.9),FReal(1.6)); - //tabPart[4] = FPoint(FReal(0.1),FReal(0.1),FReal(1.6)); - - FReal tabPhyValue[nbPart]; - tabPhyValue[0] = FReal(1); - tabPhyValue[1] = FReal(1); - tabPhyValue[2] = FReal(1); - // tabPhyValue[3] = FReal(1); - //tabPhyValue[4] = FReal(1); - - for(int l=0 ; l<nbPart ; ++l){ - tree.insert(tabPart[l],tabPhyValue[l]); - } - - KernelClass kernels(NbLevels, boxWidth, rootCenter); - FReal tabResDirect[nbPart*3]; - - for(int r=0 ; r<nbPart ; ++r){ - tabResDirect[r*3] = FReal(0); - tabResDirect[r*3+1] = FReal(0); - tabResDirect[r*3+2] = FReal(0); - } - - FReal potTheoric = FReal(0.0); - - //iteration over particles src - for(int t=0 ; t<nbPart ; ++t) - { - for(int u=t+1 ; u<nbPart ; ++u) - { - //Calcul of interaction between particules - FReal dx = tabPart[t].getX()-tabPart[u].getX(); - FReal dy = tabPart[t].getY()-tabPart[u].getY(); - FReal dz = tabPart[t].getZ()-tabPart[u].getZ(); - - FReal dist = FMath::Sqrt(dx*dx+dy*dy+dz*dz); - FReal dist2 = dx*dx+dy*dy+dz*dz; - - FReal fx = tabPhyValue[t]*tabPhyValue[u]*dx/(dist2*dist); - FReal fy = tabPhyValue[t]*tabPhyValue[u]*dy/(dist2*dist); - FReal fz = tabPhyValue[t]*tabPhyValue[u]*dz/(dist2*dist); - - - //Computation of force on part[t] - tabResDirect[t*3] += fx; - tabResDirect[t*3+1] += fy; - tabResDirect[t*3+2] += fz; - - //Computation of force on part[u] - tabResDirect[u*3] += -fx; - tabResDirect[u*3+1] += -fy; - tabResDirect[u*3+2] += -fz; - - //Computation of potential - potTheoric += tabPhyValue[t]*tabPhyValue[u]/dist; - } - } - - - FmmClass algo(&tree,&kernels); - algo.execute(); - - - - { // get sum forces&potential - FReal Energy = 0.0; - - - tree.forEachLeaf([&](LeafClass* leaf){ - FReal fx = 0.0, fy = 0.0, fz = 0.0; - const FReal * FRestrict charges = leaf->getTargets()->getPhysicalValues(); - 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){ - Energy += charges[idxPart]*potentials[idxPart]; - fx += forcesX[idxPart]; - fy += forcesY[idxPart]; - fz += forcesZ[idxPart]; - printf(" part : (%f,%F,%F), p= %f fx = %f, fy = %f, fz = %f\n",leaf->getTargets()->getPositions()[0][0],leaf->getTargets()->getPositions()[1][0],leaf->getTargets()->getPositions()[2][0],Energy,fx,fy,fz); - } - - }); - - FReal dx =tabPart[0].getX() -tabPart[1].getX(); - FReal dy =tabPart[0].getY() -tabPart[1].getY(); - FReal dz =tabPart[0].getZ() -tabPart[1].getZ(); - FReal dx1 =tabPart[2].getX() -tabPart[1].getX(); - FReal dy1 =tabPart[2].getY() -tabPart[1].getY(); - FReal dz1 =tabPart[2].getZ() -tabPart[1].getZ(); - FReal dx2 =tabPart[0].getX() -tabPart[2].getX(); - FReal dy2 =tabPart[0].getY() -tabPart[2].getY(); - FReal dz2 =tabPart[0].getZ() -tabPart[2].getZ(); - std::cout << dx <<" " <<dy <<" "<< dz <<" " <<std::endl; - std::cout << dx1 <<" " <<dy1 <<" "<< dz1 <<" " <<std::endl; - std::cout << dx2 <<" " <<dy2 <<" "<< dz2 <<" " <<std::endl; - - Energy *=FReal(0.5) ; - printf("Exact potential : %f Computed potential : %f Error: %e \n",potTheoric, Energy,std::abs(potTheoric- Energy)); - //printf("Exact Force : %f %f : %f \n",dx*coeffa,dy*coeffa,dz*coeffa); - //std::cout << Energy/potTheo << std::endl; - for (int j =0; j<nbPart ; ++j) - { - printf("particule : (%f,%f,%f) fx = %f, fy = %f, fz = %f\n",tabPart[j].getX(),tabPart[j].getY(),tabPart[j].getZ(), - tabResDirect[j*3],tabResDirect[j*3+1],tabResDirect[j*3+2]); - } - - } - return 0; - } + FPoint tabPart[3]; + tabPart[0] = FPoint(FReal(-1.9),FReal(-1.9),FReal(1.6)); + tabPart[1] = FPoint(FReal(0.9),FReal(1.1),FReal(1.6)); + tabPart[2] = FPoint(FReal(1.9),FReal(0.1),FReal(1.6)); + //tabPart[2] = FPoint(FReal(0.1),FReal(1.9),FReal(1.6)); + //tabPart[4] = FPoint(FReal(0.1),FReal(0.1),FReal(1.6)); + + FReal tabPhyValue[nbPart]; + tabPhyValue[0] = FReal(1); + tabPhyValue[1] = FReal(1); + tabPhyValue[2] = FReal(1); + // tabPhyValue[3] = FReal(1); + //tabPhyValue[4] = FReal(1); + + for(int l=0 ; l<nbPart ; ++l){ + tree.insert(tabPart[l],tabPhyValue[l]); + } + + KernelClass kernels(NbLevels, boxWidth, rootCenter); + FReal tabResDirect[nbPart*3]; + + for(int r=0 ; r<nbPart ; ++r){ + tabResDirect[r*3] = FReal(0); + tabResDirect[r*3+1] = FReal(0); + tabResDirect[r*3+2] = FReal(0); + } + + FReal potTheoric = FReal(0.0); + + //iteration over particles src + for(int t=0 ; t<nbPart ; ++t) + { + for(int u=t+1 ; u<nbPart ; ++u) + { + //Calcul of interaction between particules + FReal dx = tabPart[t].getX()-tabPart[u].getX(); + FReal dy = tabPart[t].getY()-tabPart[u].getY(); + FReal dz = tabPart[t].getZ()-tabPart[u].getZ(); + + FReal dist = FMath::Sqrt(dx*dx+dy*dy+dz*dz); + FReal dist2 = dx*dx+dy*dy+dz*dz; + + FReal fx = tabPhyValue[t]*tabPhyValue[u]*dx/(dist2*dist); + FReal fy = tabPhyValue[t]*tabPhyValue[u]*dy/(dist2*dist); + FReal fz = tabPhyValue[t]*tabPhyValue[u]*dz/(dist2*dist); + + + //Computation of force on part[t] + tabResDirect[t*3] += fx; + tabResDirect[t*3+1] += fy; + tabResDirect[t*3+2] += fz; + + //Computation of force on part[u] + tabResDirect[u*3] += -fx; + tabResDirect[u*3+1] += -fy; + tabResDirect[u*3+2] += -fz; + + //Computation of potential + potTheoric += tabPhyValue[t]*tabPhyValue[u]/dist; + } + } + + + FmmClass algo(&tree,&kernels); + algo.execute(); + + + + { // get sum forces&potential + FReal Energy = 0.0; + + + tree.forEachLeaf([&](LeafClass* leaf){ + FReal fx = 0.0, fy = 0.0, fz = 0.0; + const FReal * FRestrict charges = leaf->getTargets()->getPhysicalValues(); + 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){ + Energy += charges[idxPart]*potentials[idxPart]; + fx += forcesX[idxPart]; + fy += forcesY[idxPart]; + fz += forcesZ[idxPart]; + printf(" part : (%f,%F,%F), p= %f fx = %f, fy = %f, fz = %f\n",leaf->getTargets()->getPositions()[0][0],leaf->getTargets()->getPositions()[1][0],leaf->getTargets()->getPositions()[2][0],Energy,fx,fy,fz); + } + + }); + + FReal dx =tabPart[0].getX() -tabPart[1].getX(); + FReal dy =tabPart[0].getY() -tabPart[1].getY(); + FReal dz =tabPart[0].getZ() -tabPart[1].getZ(); + FReal dx1 =tabPart[2].getX() -tabPart[1].getX(); + FReal dy1 =tabPart[2].getY() -tabPart[1].getY(); + FReal dz1 =tabPart[2].getZ() -tabPart[1].getZ(); + FReal dx2 =tabPart[0].getX() -tabPart[2].getX(); + FReal dy2 =tabPart[0].getY() -tabPart[2].getY(); + FReal dz2 =tabPart[0].getZ() -tabPart[2].getZ(); + std::cout << dx <<" " <<dy <<" "<< dz <<" " <<std::endl; + std::cout << dx1 <<" " <<dy1 <<" "<< dz1 <<" " <<std::endl; + std::cout << dx2 <<" " <<dy2 <<" "<< dz2 <<" " <<std::endl; + + Energy *=FReal(0.5) ; + printf("Exact potential : %f Computed potential : %f Error: %e \n",potTheoric, Energy,std::abs(potTheoric- Energy)); + //printf("Exact Force : %f %f : %f \n",dx*coeffa,dy*coeffa,dz*coeffa); + //std::cout << Energy/potTheo << std::endl; + for (int j =0; j<nbPart ; ++j) + { + printf("particule : (%f,%f,%f) fx = %f, fy = %f, fz = %f\n",tabPart[j].getX(),tabPart[j].getY(),tabPart[j].getZ(), + tabResDirect[j*3],tabResDirect[j*3+1],tabResDirect[j*3+2]); + } + + } + return 0; +} diff --git a/Tests/Kernels/testTsmAlgorithm.cpp b/Tests/Kernels/testTsmAlgorithm.cpp index 19dd4af56f38f7f7e7e25174e933f27cfc6896b4..eb685ed0c0f8b899277d26f4f1f54eb8af1cc8af 100755 --- a/Tests/Kernels/testTsmAlgorithm.cpp +++ b/Tests/Kernels/testTsmAlgorithm.cpp @@ -39,6 +39,8 @@ #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that eachh particles is little or longer @@ -52,10 +54,10 @@ template <class CellClass, class ContainerClass, class LeafClass, class OctreeCl int testFunction(int argc, char ** argv, Args ... kernelPreArgs){ FTic counter; // Retrieve parameters - const int NbLevels = FParameters::getValue(argc,argv,"-depth", 5); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-subdepth", 3); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); // Get working file - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.tsm.fma"); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.tsm.fma"); std::cout << "Opening : " << filename << "\n"; // Create particles loader FFmaTsmLoader loader(filename); @@ -138,10 +140,16 @@ int testFunction(int argc, char ** argv, Args ... kernelPreArgs){ // This is the real main! int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Test the TSM (target source model) using the Rotation or the Spherical Harmonic Old implementations.", + FParameterDefinitions::OctreeHeight,FParameterDefinitions::SHDevelopment, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::InputFile, + FParameterDefinitions::SphericalKernel, FParameterDefinitions::RotationKernel); + std::cout << "[PARAM] Use Parameters -spherical -rotation -chebyshev\n"; - const int NbLevels = FParameters::getValue(argc,argv,"-h", 5); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); - if( FParameters::existParameter(argc,argv,"-spherical") ){ + if( FParameters::existParameter(argc,argv,FParameterDefinitions::SphericalKernel.options) ){ std::cout << "[INFO] -spherical is used\n"; // Create template typedef FTypedSphericalCell CellClass; @@ -153,14 +161,14 @@ int main(int argc, char ** argv){ typedef FFmmAlgorithmTsm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - const int DevP = FParameters::getValue(argc,argv,"-p", 8); + const int DevP = FParameters::getValue(argc,argv,FParameterDefinitions::SHDevelopment.options, 8); CellClass::Init(DevP); // Call Main function testFunction< CellClass, ContainerClass, LeafClass, OctreeClass, KernelClass, FmmClass>(argc, argv, DevP,NbLevels); } - if( FParameters::existParameter(argc,argv,"-rotation") ){ + if( FParameters::existParameter(argc,argv,FParameterDefinitions::RotationKernel.options) ){ std::cout << "[INFO] -rotation is used\n"; // Create template static const int P = 9; diff --git a/Tests/Kernels/testTuneSphericalBlockBlas.cpp b/Tests/Kernels/testTuneSphericalBlockBlas.cpp index 71817d4aaac13bf2457b4a399db171052264994b..8e3859125f995001a967de500df934fcd3a760df 100755 --- a/Tests/Kernels/testTuneSphericalBlockBlas.cpp +++ b/Tests/Kernels/testTuneSphericalBlockBlas.cpp @@ -42,13 +42,25 @@ #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** This program find the best block blas size */ - +static const FParameterNames LocalOptionMaxBlockSize { + {"-mbs"}, + "The maximum size of blocks." +}; // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Test the TSM (target source model) using the Rotation or the Spherical Harmonic Old implementations.", + FParameterDefinitions::OctreeHeight,FParameterDefinitions::SHDevelopment, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::InputFile, + LocalOptionMaxBlockSize); + + typedef FSphericalCell CellClass; typedef FP2PParticleContainer<> ContainerClass; @@ -60,13 +72,13 @@ int main(int argc, char ** argv){ ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test Spherical algorithm.\n"; ////////////////////////////////////////////////////////////// - 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); - const int MaxBlockSize = FParameters::getValue(argc,argv,"-mbz", 10000); + const int DevP = FParameters::getValue(argc,argv,FParameterDefinitions::SHDevelopment.options, 8); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); + const int MaxBlockSize = FParameters::getValue(argc,argv,LocalOptionMaxBlockSize.options, 10000); FTic counter; - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; // ----------------------------------------------------- diff --git a/Tests/Kernels/testUnifAlgorithm.cpp b/Tests/Kernels/testUnifAlgorithm.cpp index 6dd142667238ce489c4e5ff1b75acad5cba78b5e..8bd17c6d2005e4ce435dde7638cde62932b5200f 100644 --- a/Tests/Kernels/testUnifAlgorithm.cpp +++ b/Tests/Kernels/testUnifAlgorithm.cpp @@ -47,6 +47,8 @@ #include "Core/FFmmAlgorithm.hpp" #include "Core/FFmmAlgorithmThread.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** * This program runs the FMM Algorithm with the Uniform kernel and compares the results with a direct computation. */ @@ -54,10 +56,15 @@ // Simply create particles and try the kernels int main(int argc, char* argv[]) { - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 3); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1); + FHelpDescribeAndExit(argc, argv, + "Test Uniform kernel and compare it with the direct computation.", + FParameterDefinitions::OctreeHeight,FParameterDefinitions::NbThreads, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::InputFile); + + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); + const unsigned int TreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeHeight.options, 3); + const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeSubHeight.options, 2); + const unsigned int NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); #ifdef _OPENMP omp_set_num_threads(NbThreads); diff --git a/Tests/Kernels/testUnifAlgorithmProc.cpp b/Tests/Kernels/testUnifAlgorithmProc.cpp index 7525f934c39c5b8d10404ad100d8eb9f9366976f..cee0ae5982f9ffc9489ea0f1d4adf22fe617e69d 100644 --- a/Tests/Kernels/testUnifAlgorithmProc.cpp +++ b/Tests/Kernels/testUnifAlgorithmProc.cpp @@ -48,6 +48,9 @@ #include "../../Src/Core/FFmmAlgorithmThreadProc.hpp" #include "../../Src/BalanceTree/FLeafBalance.hpp" + +#include "../../Src/Utils/FParameterNames.hpp" + /** * This program runs the FMM Algorithm Distributed with the Uniform kernel */ @@ -55,6 +58,10 @@ // Simply create particles and try the kernel int main(int argc, char* argv[]) { + FHelpDescribeAndExit(argc, argv, + "Test Uniform kernel with MPI and compare it with the direct computation.", + FParameterDefinitions::OctreeHeight,FParameterDefinitions::NbThreads, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::InputFile); const unsigned int ORDER = 7; const FReal epsilon = FReal(1e-7); @@ -71,10 +78,10 @@ int main(int argc, char* argv[]) FMpi app(argc,argv); - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); + 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 NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); std::cout << ">> This executable has to be used to test Proc Uniform Algorithm. \n"; diff --git a/Tests/Kernels/testUnifTensorialAlgorithm.cpp b/Tests/Kernels/testUnifTensorialAlgorithm.cpp index 31b0239f55812f838af13e7cc7eee219b00645a8..a320fda3bef28885921cc83edcd55e861b739bda 100644 --- a/Tests/Kernels/testUnifTensorialAlgorithm.cpp +++ b/Tests/Kernels/testUnifTensorialAlgorithm.cpp @@ -44,6 +44,8 @@ #include "Core/FFmmAlgorithm.hpp" #include "Core/FFmmAlgorithmThread.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** * This program runs the FMM Algorithm with the Uniform kernel and compares the results with a direct computation. */ @@ -51,243 +53,248 @@ // Simply create particles and try the kernels int main(int argc, char* argv[]) { - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 3); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1); + FHelpDescribeAndExit(argc, argv, + "Test Uniform Tensorial kernel and compare it with the direct computation.", + FParameterDefinitions::OctreeHeight,FParameterDefinitions::NbThreads, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::InputFile); + + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); + const unsigned int TreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeHeight.options, 3); + const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeSubHeight.options, 2); + const unsigned int NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); #ifdef _OPENMP - omp_set_num_threads(NbThreads); - std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; + omp_set_num_threads(NbThreads); + std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; #else - std::cout << "\n>> Sequential version.\n" << std:: + std::cout << "\n>> Sequential version.\n" << std:: #endif - // init timer - FTic time; - - - // typedefs - typedef FInterpMatrixKernel_R_IJ MatrixKernelClass; - - // useful features of matrix kernel - const unsigned int NPV = MatrixKernelClass::NPV; - const unsigned int NPOT = MatrixKernelClass::NPOT; - const unsigned int NRHS = MatrixKernelClass::NRHS; - const unsigned int NLHS = MatrixKernelClass::NLHS; - - const FReal CoreWidth = 0.1; - const MatrixKernelClass MatrixKernel(CoreWidth); - - // init particles position and physical value - struct TestParticle{ - FPoint position; - FReal forces[3][NPOT]; - FReal physicalValue[NPV]; - FReal potential[NPOT]; - }; - - // open particle file - FFmaGenericLoader loader(filename); - - if(!loader.isOpen()) throw std::runtime_error("Particle file couldn't be opened!"); - - TestParticle* const particles = new TestParticle[loader.getNumberOfParticles()]; - for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - FPoint position; - FReal physicalValue = 0.0; - loader.fillParticle(&position,&physicalValue); - - // get copy - particles[idxPart].position = position; - // Set physical values - for(unsigned idxPV = 0; idxPV<NPV;++idxPV){ -// // Either copy same physical value in each component - particles[idxPart].physicalValue[idxPV] = physicalValue; - // ... or set random value -// particles[idxPart].physicalValue[idxPV] = physicalValue*FReal(drand48()); - } - for(unsigned idxPot = 0; idxPot<NPOT;++idxPot){ - particles[idxPart].potential[idxPot] = 0.0; - particles[idxPart].forces[0][idxPot] = 0.0; - particles[idxPart].forces[1][idxPot] = 0.0; - particles[idxPart].forces[2][idxPot] = 0.0; - } - } - - //////////////////////////////////////////////////////////////////// - - { // begin direct computation - std::cout << "\nDirect Computation ... " << std::endl; - time.tic(); - { - for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){ - for(int idxOther = idxTarget + 1 ; idxOther < loader.getNumberOfParticles() ; ++idxOther){ - FP2P::MutualParticlesKIJ(particles[idxTarget].position.getX(), particles[idxTarget].position.getY(), - particles[idxTarget].position.getZ(), particles[idxTarget].physicalValue, - particles[idxTarget].forces[0], particles[idxTarget].forces[1], - particles[idxTarget].forces[2], particles[idxTarget].potential, - particles[idxOther].position.getX(), particles[idxOther].position.getY(), - particles[idxOther].position.getZ(), particles[idxOther].physicalValue, - particles[idxOther].forces[0], particles[idxOther].forces[1], - particles[idxOther].forces[2], particles[idxOther].potential, - &MatrixKernel); + // init timer + FTic time; + + + // typedefs + typedef FInterpMatrixKernel_R_IJ MatrixKernelClass; + + // useful features of matrix kernel + const unsigned int NPV = MatrixKernelClass::NPV; + const unsigned int NPOT = MatrixKernelClass::NPOT; + const unsigned int NRHS = MatrixKernelClass::NRHS; + const unsigned int NLHS = MatrixKernelClass::NLHS; + + const FReal CoreWidth = 0.1; + const MatrixKernelClass MatrixKernel(CoreWidth); + + // init particles position and physical value + struct TestParticle{ + FPoint position; + FReal forces[3][NPOT]; + FReal physicalValue[NPV]; + FReal potential[NPOT]; + }; + + // open particle file + FFmaGenericLoader loader(filename); + + if(!loader.isOpen()) throw std::runtime_error("Particle file couldn't be opened!"); + + TestParticle* const particles = new TestParticle[loader.getNumberOfParticles()]; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint position; + FReal physicalValue = 0.0; + loader.fillParticle(&position,&physicalValue); + + // get copy + particles[idxPart].position = position; + // Set physical values + for(unsigned idxPV = 0; idxPV<NPV;++idxPV){ + // // Either copy same physical value in each component + particles[idxPart].physicalValue[idxPV] = physicalValue; + // ... or set random value + // particles[idxPart].physicalValue[idxPV] = physicalValue*FReal(drand48()); + } + for(unsigned idxPot = 0; idxPot<NPOT;++idxPot){ + particles[idxPart].potential[idxPot] = 0.0; + particles[idxPart].forces[0][idxPot] = 0.0; + particles[idxPart].forces[1][idxPot] = 0.0; + particles[idxPart].forces[2][idxPot] = 0.0; } - } } - time.tac(); - std::cout << "Done " << "(@Direct Computation = " - << time.elapsed() << "s)." << std::endl; - } // end direct computation + //////////////////////////////////////////////////////////////////// + + { // begin direct computation + std::cout << "\nDirect Computation ... " << std::endl; + time.tic(); + { + for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){ + for(int idxOther = idxTarget + 1 ; idxOther < loader.getNumberOfParticles() ; ++idxOther){ + FP2P::MutualParticlesKIJ(particles[idxTarget].position.getX(), particles[idxTarget].position.getY(), + particles[idxTarget].position.getZ(), particles[idxTarget].physicalValue, + particles[idxTarget].forces[0], particles[idxTarget].forces[1], + particles[idxTarget].forces[2], particles[idxTarget].potential, + particles[idxOther].position.getX(), particles[idxOther].position.getY(), + particles[idxOther].position.getZ(), particles[idxOther].physicalValue, + particles[idxOther].forces[0], particles[idxOther].forces[1], + particles[idxOther].forces[2], particles[idxOther].potential, + &MatrixKernel); + } + } + } + time.tac(); + std::cout << "Done " << "(@Direct Computation = " + << time.elapsed() << "s)." << std::endl; + + } // end direct computation - //////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// - { // begin Lagrange kernel + { // begin Lagrange kernel - // accuracy - const unsigned int ORDER = 5 ; - // set box width extension - // ... either deduce from element size - const FReal LeafCellWidth = FReal(loader.getBoxWidth()) / FReal(FMath::pow(2.,TreeHeight-1)); - const FReal ElementSize = LeafCellWidth / FReal(3.); -// const FReal BoxWidthExtension = ElementSize; // depends on type of element - // ... or set to arbitrary value (0. means no extension) - const FReal BoxWidthExtension = FReal(0.); - - std::cout << "LeafCellWidth=" << LeafCellWidth - << ", BoxWidthExtension=" << BoxWidthExtension <<std::endl; - - // stop execution if interactions are homog and box extension is required - if(MatrixKernelClass::Type==HOMOGENEOUS && BoxWidthExtension>0.) - throw std::runtime_error("Extension of box width is not yet supported for homogeneous kernels! Work-around: artificially set Type to NON_HOMOGENEOUS."); - - typedef FP2PParticleContainerIndexed<NRHS,NLHS> ContainerClass; - - typedef FSimpleLeaf< ContainerClass > LeafClass; - typedef FUnifCell<ORDER,NRHS,NLHS> CellClass; - typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; - typedef FUnifTensorialKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; - typedef FFmmAlgorithm<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; - // typedef FFmmAlgorithmThread<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; - - // init oct-tree - OctreeClass tree(TreeHeight, SubTreeHeight, loader.getBoxWidth(), loader.getCenterOfBox()); - - - { // ----------------------------------------------------- - std::cout << "Creating & Inserting " << loader.getNumberOfParticles() - << " particles ..." << std::endl; - - - - - std::cout << "\tHeight : " << TreeHeight << " \t sub-height : " << SubTreeHeight << std::endl; - time.tic(); - - for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - // put in tree - if(NPV==1) // scalar kernels like ONE_OVER_R - tree.insert(particles[idxPart].position, idxPart, - particles[idxPart].physicalValue[0]); - else if(NPV==3) // R_IJ or IOR - tree.insert(particles[idxPart].position, idxPart, - particles[idxPart].physicalValue[0], particles[idxPart].physicalValue[1], particles[idxPart].physicalValue[2]); - else - std::runtime_error("NPV not yet supported in test! Add new case."); - } - - time.tac(); - std::cout << "Done " << "(@Creating and Inserting Particles = " - << time.elapsed() << "s)." << std::endl; - } // ----------------------------------------------------- - - { // ----------------------------------------------------- - std::cout << "\nLagrange/Uniform grid FMM (ORDER="<< ORDER << ") ... " << std::endl; - time.tic(); - KernelClass kernels(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox(),&MatrixKernel,BoxWidthExtension); - FmmClass algorithm(&tree, &kernels); - algorithm.execute(); - time.tac(); - std::cout << "Done " << "(@Algorithm = " << time.elapsed() << "s)." << std::endl; - } // ----------------------------------------------------- - - - { // ----------------------------------------------------- - std::cout << "\nError computation ... " << std::endl; - FMath::FAccurater potentialDiff[NPOT]; - FMath::FAccurater fx[NPOT], fy[NPOT], fz[NPOT]; - - FReal checkPotential[20000][NPOT]; - FReal checkfx[20000][NPOT]; - - { // Check that each particle has been summed with all other - - tree.forEachLeaf([&](LeafClass* leaf){ - for(unsigned idxPot = 0; idxPot<NPOT;++idxPot){ - - const FReal*const potentials = leaf->getTargets()->getPotentials(idxPot); - const FReal*const forcesX = leaf->getTargets()->getForcesX(idxPot); - const FReal*const forcesY = leaf->getTargets()->getForcesY(idxPot); - const FReal*const forcesZ = leaf->getTargets()->getForcesZ(idxPot); - 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]; - - //PB: store potential in array[nbParticles] - checkPotential[indexPartOrig][idxPot]=potentials[idxPart]; - checkfx[indexPartOrig][idxPot]=forcesX[idxPart]; - - potentialDiff[idxPot].add(particles[indexPartOrig].potential[idxPot],potentials[idxPart]); - fx[idxPot].add(particles[indexPartOrig].forces[0][idxPot],forcesX[idxPart]); - fy[idxPot].add(particles[indexPartOrig].forces[1][idxPot],forcesY[idxPart]); - fz[idxPot].add(particles[indexPartOrig].forces[2][idxPot],forcesZ[idxPart]); - } - }// NPOT - }); - } - - - // Print for information - std::cout << "\nRelative Inf/L2 errors: " << std::endl; - std::cout << " Potential: " << std::endl; - for(unsigned idxPot = 0; idxPot<NPOT;++idxPot) { - std::cout << " " << idxPot << ": " - << potentialDiff[idxPot].getRelativeInfNorm() << ", " - << potentialDiff[idxPot].getRelativeL2Norm() - << std::endl; - } - std::cout << std::endl; - std::cout << " Fx: " << std::endl; - for(unsigned idxPot = 0; idxPot<NPOT;++idxPot) { - std::cout << " " << idxPot << ": " - << fx[idxPot].getRelativeInfNorm() << ", " - << fx[idxPot].getRelativeL2Norm() - << std::endl; - } - std::cout << std::endl; - std::cout << " Fy: " << std::endl; - for(unsigned idxPot = 0; idxPot<NPOT;++idxPot) { - std::cout << " " << idxPot << ": " - << fy[idxPot].getRelativeInfNorm() << ", " - << fy[idxPot].getRelativeL2Norm() - << std::endl; - } - std::cout << std::endl; - std::cout << " Fz: " << std::endl; - for(unsigned idxPot = 0; idxPot<NPOT;++idxPot) { - std::cout << " " << idxPot << ": " - << fz[idxPot].getRelativeInfNorm() << ", " - << fz[idxPot].getRelativeL2Norm() - << std::endl; - } - std::cout << std::endl; - - } // ----------------------------------------------------- - - } // end Lagrange kernel - - return 0; + // accuracy + const unsigned int ORDER = 5 ; + // set box width extension + // ... either deduce from element size + const FReal LeafCellWidth = FReal(loader.getBoxWidth()) / FReal(FMath::pow(2.,TreeHeight-1)); + const FReal ElementSize = LeafCellWidth / FReal(3.); + // const FReal BoxWidthExtension = ElementSize; // depends on type of element + // ... or set to arbitrary value (0. means no extension) + const FReal BoxWidthExtension = FReal(0.); + + std::cout << "LeafCellWidth=" << LeafCellWidth + << ", BoxWidthExtension=" << BoxWidthExtension <<std::endl; + + // stop execution if interactions are homog and box extension is required + if(MatrixKernelClass::Type==HOMOGENEOUS && BoxWidthExtension>0.) + throw std::runtime_error("Extension of box width is not yet supported for homogeneous kernels! Work-around: artificially set Type to NON_HOMOGENEOUS."); + + typedef FP2PParticleContainerIndexed<NRHS,NLHS> ContainerClass; + + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FUnifCell<ORDER,NRHS,NLHS> CellClass; + typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; + typedef FUnifTensorialKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; + typedef FFmmAlgorithm<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; + // typedef FFmmAlgorithmThread<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; + + // init oct-tree + OctreeClass tree(TreeHeight, SubTreeHeight, loader.getBoxWidth(), loader.getCenterOfBox()); + + + { // ----------------------------------------------------- + std::cout << "Creating & Inserting " << loader.getNumberOfParticles() + << " particles ..." << std::endl; + + + + + std::cout << "\tHeight : " << TreeHeight << " \t sub-height : " << SubTreeHeight << std::endl; + time.tic(); + + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + // put in tree + if(NPV==1) // scalar kernels like ONE_OVER_R + tree.insert(particles[idxPart].position, idxPart, + particles[idxPart].physicalValue[0]); + else if(NPV==3) // R_IJ or IOR + tree.insert(particles[idxPart].position, idxPart, + particles[idxPart].physicalValue[0], particles[idxPart].physicalValue[1], particles[idxPart].physicalValue[2]); + else + std::runtime_error("NPV not yet supported in test! Add new case."); + } + + time.tac(); + std::cout << "Done " << "(@Creating and Inserting Particles = " + << time.elapsed() << "s)." << std::endl; + } // ----------------------------------------------------- + + { // ----------------------------------------------------- + std::cout << "\nLagrange/Uniform grid FMM (ORDER="<< ORDER << ") ... " << std::endl; + time.tic(); + KernelClass kernels(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox(),&MatrixKernel,BoxWidthExtension); + FmmClass algorithm(&tree, &kernels); + algorithm.execute(); + time.tac(); + std::cout << "Done " << "(@Algorithm = " << time.elapsed() << "s)." << std::endl; + } // ----------------------------------------------------- + + + { // ----------------------------------------------------- + std::cout << "\nError computation ... " << std::endl; + FMath::FAccurater potentialDiff[NPOT]; + FMath::FAccurater fx[NPOT], fy[NPOT], fz[NPOT]; + + FReal checkPotential[20000][NPOT]; + FReal checkfx[20000][NPOT]; + + { // Check that each particle has been summed with all other + + tree.forEachLeaf([&](LeafClass* leaf){ + for(unsigned idxPot = 0; idxPot<NPOT;++idxPot){ + + const FReal*const potentials = leaf->getTargets()->getPotentials(idxPot); + const FReal*const forcesX = leaf->getTargets()->getForcesX(idxPot); + const FReal*const forcesY = leaf->getTargets()->getForcesY(idxPot); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(idxPot); + 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]; + + //PB: store potential in array[nbParticles] + checkPotential[indexPartOrig][idxPot]=potentials[idxPart]; + checkfx[indexPartOrig][idxPot]=forcesX[idxPart]; + + potentialDiff[idxPot].add(particles[indexPartOrig].potential[idxPot],potentials[idxPart]); + fx[idxPot].add(particles[indexPartOrig].forces[0][idxPot],forcesX[idxPart]); + fy[idxPot].add(particles[indexPartOrig].forces[1][idxPot],forcesY[idxPart]); + fz[idxPot].add(particles[indexPartOrig].forces[2][idxPot],forcesZ[idxPart]); + } + }// NPOT + }); + } + + + // Print for information + std::cout << "\nRelative Inf/L2 errors: " << std::endl; + std::cout << " Potential: " << std::endl; + for(unsigned idxPot = 0; idxPot<NPOT;++idxPot) { + std::cout << " " << idxPot << ": " + << potentialDiff[idxPot].getRelativeInfNorm() << ", " + << potentialDiff[idxPot].getRelativeL2Norm() + << std::endl; + } + std::cout << std::endl; + std::cout << " Fx: " << std::endl; + for(unsigned idxPot = 0; idxPot<NPOT;++idxPot) { + std::cout << " " << idxPot << ": " + << fx[idxPot].getRelativeInfNorm() << ", " + << fx[idxPot].getRelativeL2Norm() + << std::endl; + } + std::cout << std::endl; + std::cout << " Fy: " << std::endl; + for(unsigned idxPot = 0; idxPot<NPOT;++idxPot) { + std::cout << " " << idxPot << ": " + << fy[idxPot].getRelativeInfNorm() << ", " + << fy[idxPot].getRelativeL2Norm() + << std::endl; + } + std::cout << std::endl; + std::cout << " Fz: " << std::endl; + for(unsigned idxPot = 0; idxPot<NPOT;++idxPot) { + std::cout << " " << idxPot << ": " + << fz[idxPot].getRelativeInfNorm() << ", " + << fz[idxPot].getRelativeL2Norm() + << std::endl; + } + std::cout << std::endl; + + } // ----------------------------------------------------- + + } // end Lagrange kernel + + return 0; } diff --git a/Tests/Utils/testBlas.cpp b/Tests/Utils/testBlas.cpp index 157f8c17b3467d87f0591dc800c4ffde91af7e8a..7c419fccb7bad9186a90dba07c96b68212c7d63d 100755 --- a/Tests/Utils/testBlas.cpp +++ b/Tests/Utils/testBlas.cpp @@ -23,14 +23,18 @@ #include "../../Src/Utils/FBlas.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + FReal FRandom() { return (FReal(drand48())); } /** * Test functionality of C - interfaced BLAS functions */ -int main() +int main(int argc, char** argv) { + FHelpDescribeAndExit(argc, argv, "Simply ensure that blas are compuling and running."); + const unsigned int m = 4, n = 4; // to be able to test both, transpose and not transpose operations FReal* A = new FReal [m * n]; // matrix: column major ordering FReal* x = new FReal [n]; diff --git a/Tests/Utils/testChebBinaryM2L.cpp b/Tests/Utils/testChebBinaryM2L.cpp index 34a7c9ba107c0c926bdcafec451ebbacc98af046..d52b048c14e2d7b4fc49b36106e4ac84e61488f8 100755 --- a/Tests/Utils/testChebBinaryM2L.cpp +++ b/Tests/Utils/testChebBinaryM2L.cpp @@ -32,7 +32,7 @@ #include "../../Src/Kernels/Interpolation/FInterpMatrixKernel.hpp" #include "../../Src/Kernels/Chebyshev/FChebM2LHandler.hpp" - +#include "../../Src/Utils/FParameterNames.hpp" /** @@ -40,6 +40,8 @@ */ int main(int argc, char* argv[]) { + FHelpDescribeAndExit(argc, argv, "Just generate Chebyshev M2L matrices for several orders."); + // typedefs typedef FInterpMatrixKernelR MatrixKernelClass; diff --git a/Tests/Utils/testChebBinarySymM2L.cpp b/Tests/Utils/testChebBinarySymM2L.cpp index 958d5ea9d69f9e322a7bfcaafa19eb13148e7bda..ac0ed80e054f2945174aa57d0465f07bcd5a3d1b 100755 --- a/Tests/Utils/testChebBinarySymM2L.cpp +++ b/Tests/Utils/testChebBinarySymM2L.cpp @@ -33,7 +33,7 @@ #include "../../Src/Kernels/Interpolation/FInterpMatrixKernel.hpp" #include "../../Src/Kernels/Chebyshev/FChebSymM2LHandler.hpp" - +#include "../../Src/Utils/FParameterNames.hpp" /** @@ -41,6 +41,8 @@ */ int main(int argc, char* argv[]) { + FHelpDescribeAndExit(argc, argv, "Generate and store Chebyshev M2L matrices for several orders."); + // typedefs typedef FInterpMatrixKernelR MatrixKernelClass; diff --git a/Tests/Utils/testChebInterpolator.cpp b/Tests/Utils/testChebInterpolator.cpp index 6377596ed7acb66223156fe8812953eeca646896..7d42e86c1cd3e03f8aefa121aa1ad86e9a3e193a 100755 --- a/Tests/Utils/testChebInterpolator.cpp +++ b/Tests/Utils/testChebInterpolator.cpp @@ -40,14 +40,16 @@ #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" #include "../../Src/Components/FSimpleLeaf.hpp" - +#include "../../Src/Utils/FParameterNames.hpp" /** * In this file we show how to use octree */ -int main(int, char **){ +int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, "Test Chebyshev interpolator."); + typedef FP2PParticleContainer<> ContainerClass; typedef FSimpleLeaf<ContainerClass> LeafClass; typedef FInterpMatrixKernelR MatrixKernelClass; diff --git a/Tests/Utils/testChebInterpolatorExtendedBBox.cpp b/Tests/Utils/testChebInterpolatorExtendedBBox.cpp index c90db428fa9731b8a52327ffe7dd9309b47eabcf..67c384fdaba7f0faa2d9b995d7e0ba7d184e77c4 100644 --- a/Tests/Utils/testChebInterpolatorExtendedBBox.cpp +++ b/Tests/Utils/testChebInterpolatorExtendedBBox.cpp @@ -40,7 +40,7 @@ #include "Kernels/P2P/FP2PParticleContainer.hpp" #include "Components/FSimpleLeaf.hpp" - +#include "../../Src/Utils/FParameterNames.hpp" /** @@ -50,7 +50,9 @@ * in the extended bounding box of each clusters. */ -int main(int, char **){ +int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, "Test Chebyshev interpolator."); + typedef FP2PParticleContainer<> ContainerClass; typedef FSimpleLeaf<ContainerClass> LeafClass; typedef FInterpMatrixKernelR MatrixKernelClass; diff --git a/Tests/Utils/testChebM2Lprecomputation.cpp b/Tests/Utils/testChebM2Lprecomputation.cpp index 67ab5527585aafc1e8e681db732f745d98bd337c..2b4909dd97d28129a9b0af26044ffe1fa63d2490 100755 --- a/Tests/Utils/testChebM2Lprecomputation.cpp +++ b/Tests/Utils/testChebM2Lprecomputation.cpp @@ -34,144 +34,147 @@ #include "../../Src/Kernels/Chebyshev/FChebM2LHandler.hpp" #include "../../Src/Kernels/Interpolation/FInterpMatrixKernel.hpp" - +#include "../../Src/Utils/FParameterNames.hpp" int main(int argc, char* argv[]) { - // start timer ///////////////////////////////// - FTic time; - - // define set matrix kernel - typedef FInterpMatrixKernelR MatrixKernelClass; - MatrixKernelClass MatrixKernel; - - // constants - const FReal epsilon = FReal(atof(argv[1])); - const unsigned int order = 9; - - // number of interpolation points per cell - const unsigned int nnodes = TensorTraits<order>::nnodes; - - // interpolation points of source (Y) and target (X) cell - FPoint X[nnodes], Y[nnodes]; - // set roots of target cell (X) - FChebTensor<order>::setRoots(FPoint(0.,0.,0.), FReal(2.), X); - - - /* - // allocate memory - FReal *Qu, *C, *Qb; - Qu = Qb = C = nullptr; - unsigned int ninteractions = 0; - - //////////////////////////////////////////////// - std::cout << "\nAssembly of 316 times " - << nnodes << "x" << nnodes << " M2L operators"; - time.tic(); - // compute 316 m2l operators - ninteractions = 316; - C = new FReal [nnodes*nnodes * ninteractions]; - unsigned int counter = 0; - for (int i=-3; i<=3; ++i) { - for (int j=-3; j<=3; ++j) { - for (int k=-3; k<=3; ++k) { - if (abs(i)>1 || abs(j)>1 || abs(k)>1) { - // set roots of source cell (Y) - const FPoint cy(FReal(2.*i), FReal(2.*j), FReal(2.*k)); - FChebTensor<order>::setRoots(cy, FReal(2.), Y); - // evaluate m2l operator - for (unsigned int n=0; n<nnodes; ++n) - for (unsigned int m=0; m<nnodes; ++m) - C[counter*nnodes*nnodes + n*nnodes + m] = MatrixKernel.evaluate(X[m], Y[n]); - // increment interaction counter - counter++; - } - } - } - } - if (counter != 316) - std::runtime_error("Number of interactions must correspond to 316"); - std::cout << " took " << time.tacAndElapsed() << " sec." << std::endl; - //////////////////////////////////////////////// - - //////////////////////////////////////////////// - std::cout << "\nSVD compression "; - time.tic(); - const unsigned int rank = Compress<order>(epsilon, ninteractions, Qu, C, Qb); - std::cout << "to low rank = " << rank << " (eps = " << epsilon - << ") took " << time.tacAndElapsed() << " sec." << std::endl; - //////////////////////////////////////////////// - - // free memory - if (C != nullptr) delete [] C; - if (Qu != nullptr) delete [] Qu; - if (Qb != nullptr) delete [] Qb; - */ - - //////////////////////////////////////////////// - // allocate memory - FReal *Qu1, *C1, *Qb1; - Qu1 = Qb1 = C1 = nullptr; - //////////////////////////////////////////////// - std::cout << "\nAssembly of an " << nnodes << "x" << nnodes << " M2L operator"; - time.tic(); - // compute 316 m2l operators - C1 = new FReal [nnodes*nnodes]; - const unsigned int i = 3; - const unsigned int j = 3; - const unsigned int k = 3; - const FPoint cy(FReal(2.*i), FReal(2.*j), FReal(2.*k)); - FChebTensor<order>::setRoots(cy, FReal(2.), Y); - // evaluate m2l operator - for (unsigned int n=0; n<nnodes; ++n) - for (unsigned int m=0; m<nnodes; ++m) - C1[n*nnodes + m] = MatrixKernel.evaluate(X[m], Y[n]); - std::cout << " took " << time.tacAndElapsed() << " sec." << std::endl; - //////////////////////////////////////////////// - - //////////////////////////////////////////////// - // get a copy C2 of the M2L operator C1 - FReal *Qu2, *C2, *Qb2; - Qu2 = Qb2 = C2 = nullptr; - C2 = new FReal [nnodes * nnodes]; - FBlas::copy(nnodes*nnodes, C1, C2); - // Omega_x^{1/2} C2 Omega_y^{1/2} - FReal weights[nnodes]; - FChebTensor<order>::setRootOfWeights(weights); - for (unsigned int n=0; n<nnodes; ++n) { - FBlas::scal(nnodes, weights[n], C2+n, nnodes); // scale rows - FBlas::scal(nnodes, weights[n], C2+n*nnodes); // scale cols - } - //////////////////////////////////////////////// - - //////////////////////////////////////////////// - std::cout << "\nSVD compression of K "; - time.tic(); - const unsigned int rank1 = Compress<order>(epsilon, 1, Qu1, C1, Qb1); - std::cout << "to low rank = " << rank1 << " (eps = " << epsilon - << ") took " << time.tacAndElapsed() << " sec." << std::endl; - //////////////////////////////////////////////// - - //////////////////////////////////////////////// - std::cout << "SVD compression of Omega_x^{1/2} K Omega_y^{1/2} "; - time.tic(); - const unsigned int rank2 = Compress<order>(epsilon, 1, Qu2, C2, Qb2); - std::cout << "to low rank = " << rank2 << " (eps = " << epsilon - << ") took " << time.tacAndElapsed() << " sec." << std::endl; - //////////////////////////////////////////////// - - // free memory - if (C1 != nullptr) delete [] C1; - if (Qu1 != nullptr) delete [] Qu1; - if (Qb1 != nullptr) delete [] Qb1; - - if (C2 != nullptr) delete [] C2; - if (Qu2 != nullptr) delete [] Qu2; - if (Qb2 != nullptr) delete [] Qb2; - - - return 0; + FHelpDescribeAndExit(argc, argv, "Test Chebyshev precomputation.", + FParameterDefinitions::Epsilon); + + // start timer ///////////////////////////////// + FTic time; + + // define set matrix kernel + typedef FInterpMatrixKernelR MatrixKernelClass; + MatrixKernelClass MatrixKernel; + + // constants + const FReal epsilon = FParameters::getValue(argc, argv, FParameterDefinitions::Epsilon.options, FReal(0.1)); + const unsigned int order = 9; + + // number of interpolation points per cell + const unsigned int nnodes = TensorTraits<order>::nnodes; + + // interpolation points of source (Y) and target (X) cell + FPoint X[nnodes], Y[nnodes]; + // set roots of target cell (X) + FChebTensor<order>::setRoots(FPoint(0.,0.,0.), FReal(2.), X); + + + /* + // allocate memory + FReal *Qu, *C, *Qb; + Qu = Qb = C = nullptr; + unsigned int ninteractions = 0; + + //////////////////////////////////////////////// + std::cout << "\nAssembly of 316 times " + << nnodes << "x" << nnodes << " M2L operators"; + time.tic(); + // compute 316 m2l operators + ninteractions = 316; + C = new FReal [nnodes*nnodes * ninteractions]; + unsigned int counter = 0; + for (int i=-3; i<=3; ++i) { + for (int j=-3; j<=3; ++j) { + for (int k=-3; k<=3; ++k) { + if (abs(i)>1 || abs(j)>1 || abs(k)>1) { + // set roots of source cell (Y) + const FPoint cy(FReal(2.*i), FReal(2.*j), FReal(2.*k)); + FChebTensor<order>::setRoots(cy, FReal(2.), Y); + // evaluate m2l operator + for (unsigned int n=0; n<nnodes; ++n) + for (unsigned int m=0; m<nnodes; ++m) + C[counter*nnodes*nnodes + n*nnodes + m] = MatrixKernel.evaluate(X[m], Y[n]); + // increment interaction counter + counter++; + } + } + } + } + if (counter != 316) + std::runtime_error("Number of interactions must correspond to 316"); + std::cout << " took " << time.tacAndElapsed() << " sec." << std::endl; + //////////////////////////////////////////////// + + //////////////////////////////////////////////// + std::cout << "\nSVD compression "; + time.tic(); + const unsigned int rank = Compress<order>(epsilon, ninteractions, Qu, C, Qb); + std::cout << "to low rank = " << rank << " (eps = " << epsilon + << ") took " << time.tacAndElapsed() << " sec." << std::endl; + //////////////////////////////////////////////// + + // free memory + if (C != nullptr) delete [] C; + if (Qu != nullptr) delete [] Qu; + if (Qb != nullptr) delete [] Qb; + */ + + //////////////////////////////////////////////// + // allocate memory + FReal *Qu1, *C1, *Qb1; + Qu1 = Qb1 = C1 = nullptr; + //////////////////////////////////////////////// + std::cout << "\nAssembly of an " << nnodes << "x" << nnodes << " M2L operator"; + time.tic(); + // compute 316 m2l operators + C1 = new FReal [nnodes*nnodes]; + const unsigned int i = 3; + const unsigned int j = 3; + const unsigned int k = 3; + const FPoint cy(FReal(2.*i), FReal(2.*j), FReal(2.*k)); + FChebTensor<order>::setRoots(cy, FReal(2.), Y); + // evaluate m2l operator + for (unsigned int n=0; n<nnodes; ++n) + for (unsigned int m=0; m<nnodes; ++m) + C1[n*nnodes + m] = MatrixKernel.evaluate(X[m], Y[n]); + std::cout << " took " << time.tacAndElapsed() << " sec." << std::endl; + //////////////////////////////////////////////// + + //////////////////////////////////////////////// + // get a copy C2 of the M2L operator C1 + FReal *Qu2, *C2, *Qb2; + Qu2 = Qb2 = C2 = nullptr; + C2 = new FReal [nnodes * nnodes]; + FBlas::copy(nnodes*nnodes, C1, C2); + // Omega_x^{1/2} C2 Omega_y^{1/2} + FReal weights[nnodes]; + FChebTensor<order>::setRootOfWeights(weights); + for (unsigned int n=0; n<nnodes; ++n) { + FBlas::scal(nnodes, weights[n], C2+n, nnodes); // scale rows + FBlas::scal(nnodes, weights[n], C2+n*nnodes); // scale cols + } + //////////////////////////////////////////////// + + //////////////////////////////////////////////// + std::cout << "\nSVD compression of K "; + time.tic(); + const unsigned int rank1 = Compress<order>(epsilon, 1, Qu1, C1, Qb1); + std::cout << "to low rank = " << rank1 << " (eps = " << epsilon + << ") took " << time.tacAndElapsed() << " sec." << std::endl; + //////////////////////////////////////////////// + + //////////////////////////////////////////////// + std::cout << "SVD compression of Omega_x^{1/2} K Omega_y^{1/2} "; + time.tic(); + const unsigned int rank2 = Compress<order>(epsilon, 1, Qu2, C2, Qb2); + std::cout << "to low rank = " << rank2 << " (eps = " << epsilon + << ") took " << time.tacAndElapsed() << " sec." << std::endl; + //////////////////////////////////////////////// + + // free memory + if (C1 != nullptr) delete [] C1; + if (Qu1 != nullptr) delete [] Qu1; + if (Qb1 != nullptr) delete [] Qb1; + + if (C2 != nullptr) delete [] C2; + if (Qu2 != nullptr) delete [] Qu2; + if (Qb2 != nullptr) delete [] Qb2; + + + return 0; } diff --git a/Tests/Utils/testChebOctree.cpp b/Tests/Utils/testChebOctree.cpp index 7caab51fbd4ef2e4114566195ccf5727e117e371..f56be1f333c321080b6b29926ce5c9d433571edb 100755 --- a/Tests/Utils/testChebOctree.cpp +++ b/Tests/Utils/testChebOctree.cpp @@ -38,11 +38,14 @@ #include "../../Src/Components/FSimpleLeaf.hpp" #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** * In this file we show how to use octree */ -int main(int, char **){ +int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, "Test the octree with the Chebyshev kernel."); const int ORDER = 5; diff --git a/Tests/Utils/testChebSxUCBSy.cpp b/Tests/Utils/testChebSxUCBSy.cpp index a4fb6322cacdae90dc29940a49caf8412754a4cb..c57bf6b24249c572284058ebf16111e53f594179 100755 --- a/Tests/Utils/testChebSxUCBSy.cpp +++ b/Tests/Utils/testChebSxUCBSy.cpp @@ -40,6 +40,8 @@ #include "../../Src/Components/FSimpleLeaf.hpp" #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + void applyM2M(FReal *const S, FReal *const w, const unsigned int n, FReal *const W, const unsigned int N) { FBlas::gemtva(n, N, FReal(1.), S, w, W); } @@ -50,6 +52,8 @@ void applyM2M(FReal *const S, FReal *const w, const unsigned int n, FReal *const int main(int argc, char* argv[]) { + FHelpDescribeAndExit(argc, argv, "Test Chebyshev interation computations."); + typedef FP2PParticleContainer<> ContainerClass; typedef FSimpleLeaf<ContainerClass> LeafClass; typedef FInterpMatrixKernelR MatrixKernelClass; diff --git a/Tests/Utils/testChebSymmetries.cpp b/Tests/Utils/testChebSymmetries.cpp index 49e4ec84d9d198e6f2bae0513150b057c51ebe31..b3518478696dd9ad37b117ce931988c43f21361f 100755 --- a/Tests/Utils/testChebSymmetries.cpp +++ b/Tests/Utils/testChebSymmetries.cpp @@ -33,20 +33,20 @@ #include "../../Src/Kernels/Interpolation/FInterpMatrixKernel.hpp" #include "../../Src/Kernels/Interpolation/FInterpSymmetries.hpp" - +#include "../../Src/Utils/FParameterNames.hpp" template <int ORDER> void permuteMatrix(const unsigned int perm[ORDER*ORDER*ORDER], FReal *const Matrix) { - const unsigned int nnodes = ORDER*ORDER*ORDER; - // allocate temporary memory for matrix - FReal temp[nnodes*nnodes]; - // permute rows - for (unsigned int r=0; r<nnodes; ++r) - FBlas::copy(nnodes, Matrix+r, nnodes, temp+perm[r], nnodes); - // permute columns - for (unsigned int c=0; c<nnodes; ++c) - FBlas::copy(nnodes, temp + c * nnodes, Matrix + perm[c] * nnodes); + const unsigned int nnodes = ORDER*ORDER*ORDER; + // allocate temporary memory for matrix + FReal temp[nnodes*nnodes]; + // permute rows + for (unsigned int r=0; r<nnodes; ++r) + FBlas::copy(nnodes, Matrix+r, nnodes, temp+perm[r], nnodes); + // permute columns + for (unsigned int c=0; c<nnodes; ++c) + FBlas::copy(nnodes, temp + c * nnodes, Matrix + perm[c] * nnodes); } @@ -55,107 +55,109 @@ void permuteMatrix(const unsigned int perm[ORDER*ORDER*ORDER], FReal *const Matr int main(int argc, char* argv[]) { - // start timer ///////////////////////////////// - FTic time; - - // define set matrix kernel - typedef FInterpMatrixKernelR MatrixKernelClass; - MatrixKernelClass MatrixKernel; - - // constants - //const FReal epsilon = FReal(atof(argv[1])); - const unsigned int order = 5; - - // number of interpolation points per cell - const unsigned int nnodes = TensorTraits<order>::nnodes; - - // interpolation points of source (Y) and target (X) cell - FPoint X[nnodes], Y[nnodes]; - // set roots of target cell (X) - FChebTensor<order>::setRoots(FPoint(0.,0.,0.), FReal(2.), X); - - // allocate 343 pointers to K, but only 16 are actually filled - FReal** K = new FReal* [343]; - for (unsigned int t=0; t<343; ++t) K[t] = nullptr; - - { - unsigned int counter = 0; - - for (int i=2; i<=3; ++i) { - for (int j=0; j<=i; ++j) { - for (int k=0; k<=j; ++k) { - - const unsigned int idx = (i+3)*7*7 + (j+3)*7 + (k+3); - K[idx] = new FReal [nnodes*nnodes]; - - //std::cout << i << "," << j << "," << k << "\t" << idx << std::endl; - - const FPoint cy(FReal(2.*i), FReal(2.*j), FReal(2.*k)); - FChebTensor<order>::setRoots(cy, FReal(2.), Y); - for (unsigned int n=0; n<nnodes; ++n) - for (unsigned int m=0; m<nnodes; ++m) - K[idx][n*nnodes + m] = MatrixKernel.evaluate(X[m], Y[n]); - - counter++; - } - } - } - - std::cout << "num interactions = " << counter << std::endl; - } - - // max difference - FReal maxdiff(0.); - - // permuter - FInterpSymmetries<order> permuter; - - // permutation vector - unsigned int perm[nnodes]; - - FReal* K0 = new FReal [nnodes*nnodes]; - - unsigned int counter = 0; - - for (int i=-3; i<=3; ++i) { - for (int j=-3; j<=3; ++j) { - for (int k=-3; k<=3; ++k) { - if (abs(i)>1 || abs(j)>1 || abs(k)>1) { - - const FPoint cy(FReal(2.*i), FReal(2.*j), FReal(2.*k)); - FChebTensor<order>::setRoots(cy, FReal(2.), Y); - for (unsigned int n=0; n<nnodes; ++n) - for (unsigned int m=0; m<nnodes; ++m) - K0[n*nnodes + m] = MatrixKernel.evaluate(X[m], Y[n]); - - // permute - const unsigned int pidx = permuter.getPermutationArrayAndIndex(i, j, k, perm); - permuteMatrix<order>(perm, K0); - - if (K[pidx]==NULL) std::cout << " - not existing index " << pidx << std::endl; - - FReal mdiff(0.); - for (unsigned int n=0; n<nnodes*nnodes; ++n) { - FReal diff(K0[n] - K[pidx][n]); - if (FMath::Abs(diff)>mdiff) mdiff = diff; - } - if (FMath::Abs(mdiff)>maxdiff) maxdiff = FMath::Abs(mdiff); - - if (mdiff > 1e-15) exit(-1); - counter++; - - } - } - } - } - - std::cout << "Max error = " << maxdiff << " of counter = " << counter << std::endl; - - for (unsigned int t=0; t<343; ++t) if (K[t]!=NULL) delete [] K[t]; - delete [] K; - delete [] K0; - - return 0; + FHelpDescribeAndExit(argc, argv, "Test Chebyshev symmetries."); + + // start timer ///////////////////////////////// + FTic time; + + // define set matrix kernel + typedef FInterpMatrixKernelR MatrixKernelClass; + MatrixKernelClass MatrixKernel; + + // constants + //const FReal epsilon = FReal(atof(argv[1])); + const unsigned int order = 5; + + // number of interpolation points per cell + const unsigned int nnodes = TensorTraits<order>::nnodes; + + // interpolation points of source (Y) and target (X) cell + FPoint X[nnodes], Y[nnodes]; + // set roots of target cell (X) + FChebTensor<order>::setRoots(FPoint(0.,0.,0.), FReal(2.), X); + + // allocate 343 pointers to K, but only 16 are actually filled + FReal** K = new FReal* [343]; + for (unsigned int t=0; t<343; ++t) K[t] = nullptr; + + { + unsigned int counter = 0; + + for (int i=2; i<=3; ++i) { + for (int j=0; j<=i; ++j) { + for (int k=0; k<=j; ++k) { + + const unsigned int idx = (i+3)*7*7 + (j+3)*7 + (k+3); + K[idx] = new FReal [nnodes*nnodes]; + + //std::cout << i << "," << j << "," << k << "\t" << idx << std::endl; + + const FPoint cy(FReal(2.*i), FReal(2.*j), FReal(2.*k)); + FChebTensor<order>::setRoots(cy, FReal(2.), Y); + for (unsigned int n=0; n<nnodes; ++n) + for (unsigned int m=0; m<nnodes; ++m) + K[idx][n*nnodes + m] = MatrixKernel.evaluate(X[m], Y[n]); + + counter++; + } + } + } + + std::cout << "num interactions = " << counter << std::endl; + } + + // max difference + FReal maxdiff(0.); + + // permuter + FInterpSymmetries<order> permuter; + + // permutation vector + unsigned int perm[nnodes]; + + FReal* K0 = new FReal [nnodes*nnodes]; + + unsigned int counter = 0; + + for (int i=-3; i<=3; ++i) { + for (int j=-3; j<=3; ++j) { + for (int k=-3; k<=3; ++k) { + if (abs(i)>1 || abs(j)>1 || abs(k)>1) { + + const FPoint cy(FReal(2.*i), FReal(2.*j), FReal(2.*k)); + FChebTensor<order>::setRoots(cy, FReal(2.), Y); + for (unsigned int n=0; n<nnodes; ++n) + for (unsigned int m=0; m<nnodes; ++m) + K0[n*nnodes + m] = MatrixKernel.evaluate(X[m], Y[n]); + + // permute + const unsigned int pidx = permuter.getPermutationArrayAndIndex(i, j, k, perm); + permuteMatrix<order>(perm, K0); + + if (K[pidx]==NULL) std::cout << " - not existing index " << pidx << std::endl; + + FReal mdiff(0.); + for (unsigned int n=0; n<nnodes*nnodes; ++n) { + FReal diff(K0[n] - K[pidx][n]); + if (FMath::Abs(diff)>mdiff) mdiff = diff; + } + if (FMath::Abs(mdiff)>maxdiff) maxdiff = FMath::Abs(mdiff); + + if (mdiff > 1e-15) exit(-1); + counter++; + + } + } + } + } + + std::cout << "Max error = " << maxdiff << " of counter = " << counter << std::endl; + + for (unsigned int t=0; t<343; ++t) if (K[t]!=NULL) delete [] K[t]; + delete [] K; + delete [] K0; + + return 0; } diff --git a/Tests/Utils/testChebTensorProduct.cpp b/Tests/Utils/testChebTensorProduct.cpp index 0f2132667eb3a0195f9b9de91961cae0200acb9c..190fba890d01758f8def42e0ce4a0bcbee289be7 100755 --- a/Tests/Utils/testChebTensorProduct.cpp +++ b/Tests/Utils/testChebTensorProduct.cpp @@ -38,6 +38,8 @@ #include "../../Src/Kernels/Chebyshev/FChebTensor.hpp" #include "../../Src/Kernels/Chebyshev/FChebInterpolator.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + void applyM2M(FReal *const S, FReal *const w, const unsigned int n, FReal *const W, const unsigned int N) { FBlas::gemtva(n, N, FReal(1.), S, w, W); } @@ -57,7 +59,8 @@ void applyl2l(FReal *const S, FReal *const F, const unsigned int n, FReal *const int main(int argc, char* argv[]) { - FTic time; + FHelpDescribeAndExit(argc, argv, "Test Chebyshev tensor product."); + const unsigned int ORDER = 10; const unsigned int nnodes = TensorTraits<ORDER>::nnodes; FPoint X[nnodes]; diff --git a/Tests/Utils/testCompareIOTree.cpp b/Tests/Utils/testCompareIOTree.cpp index 19db9d04d2a4812b606eed334be7d910ea45b55c..2a2aa1d3f0aa164cf4cb363147aeb1acf9138e35 100755 --- a/Tests/Utils/testCompareIOTree.cpp +++ b/Tests/Utils/testCompareIOTree.cpp @@ -33,8 +33,18 @@ #include "../../Src/Components/FSimpleLeaf.hpp" #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + // Simply create particles and try the kernels int main(int argc, char ** argv){ + + FHelpDescribeAndExit(argc, argv, + "Load octrees that have been saved and compare everything from leaves to cells.\n" + "Using the Spherical Harmonics old kernel.", + FParameterDefinitions::SHDevelopment, FParameterDefinitions::InputFileOne, + FParameterDefinitions::InputFileTwow + ); + typedef FSphericalCell CellClass; typedef FP2PParticleContainer<> ContainerClass; @@ -43,7 +53,7 @@ int main(int argc, char ** argv){ ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to compare two trees.\n"; ////////////////////////////////////////////////////////////// - const int DevP = FParameters::getValue(argc,argv,"-p", 8); + const int DevP = FParameters::getValue(argc,argv,FParameterDefinitions::SHDevelopment.options, 8); // ----------------------------------------------------- CellClass::Init(DevP, true); @@ -51,8 +61,8 @@ int main(int argc, char ** argv){ OctreeClass tree2(5, 3, 0, FPoint()); // ----------------------------------------------------- - const char* const filename1 = FParameters::getStr(argc,argv,"-f1", "tree.data"); - const char* const filename2 = FParameters::getStr(argc,argv,"-f2", "dtree.data"); + const char* const filename1 = FParameters::getStr(argc,argv,FParameterDefinitions::InputFileOne.options, "tree.data"); + const char* const filename2 = FParameters::getStr(argc,argv,FParameterDefinitions::InputFileOne.options, "dtree.data"); std::cout << "Compare tree " << filename1 << " and " << filename2 << std::endl; FTreeIO::Load<OctreeClass, CellClass, LeafClass, ContainerClass >(filename1, tree1); diff --git a/Tests/Utils/testDebug.cpp b/Tests/Utils/testDebug.cpp index 629954e01f1f756a238a9666ffbdc7b78fd1e748..e3e243c0c2c6824452eafc1e61729d348bdebacd 100755 --- a/Tests/Utils/testDebug.cpp +++ b/Tests/Utils/testDebug.cpp @@ -15,12 +15,15 @@ // =================================================================================== #include "../../Src/Utils/FLog.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** * In this file we show how to use the debug module. * Warning, in FGlobal.hpp (included in FLog.hpp) ScalFMM_USE_DEBUG might be undefined. */ -int main(void){ +int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, "Just show how the debug and log stuff should be used."); ///////////////////////What we do///////////////////////////// std::cout << ">> This executable is useless to execute.\n"; std::cout << ">> It is only interesting to wath the code to understand\n"; diff --git a/Tests/Utils/testFFTW.cpp b/Tests/Utils/testFFTW.cpp index b91e020b4be283f6d1f775390389fa9015ac35e9..ae0f2d7330b07c8f64028c376b41f37a4b033675 100644 --- a/Tests/Utils/testFFTW.cpp +++ b/Tests/Utils/testFFTW.cpp @@ -28,112 +28,115 @@ #include "../../Src/Utils/FTic.hpp" +#include "../../Src/Utils/FParameterNames.hpp" //#include "../../Src/Utils/FDft.hpp" -int main() +int main(int argc, char** argv) { - const FReal FRandMax = FReal(RAND_MAX); - - FTic time; - - ////////////////////////////////////////////////////////////////////////////// - // INITIALIZATION - - // size (pick a power of 2 for better performance of the FFT algorithm) - unsigned int nsteps_ = 500; - - // fftw arrays - FReal* fftR_; - FComplex* fftC_; - - fftR_ = (FReal*) fftw_malloc(sizeof(FReal) * nsteps_); - fftC_ = (FComplex*) fftw_malloc(sizeof(FComplex) * nsteps_); - - // fftw plans - // use routine defined in file: - // /PATH/TO/mkl/interfaces/fftw3xf/wrappers/fftw_plan_dft_c2r_1d.c - fftw_plan plan_c2r_; // backward FFT plan - fftw_plan plan_r2c_; // forward FFT plan - - std::cout<< "Init FFTW plans: "; - time.tic(); - - plan_c2r_ = - fftw_plan_dft_c2r_1d(nsteps_, - reinterpret_cast<fftw_complex*>(fftC_), - fftR_, - FFTW_MEASURE); - plan_r2c_ = - fftw_plan_dft_r2c_1d(nsteps_, - fftR_, - reinterpret_cast<fftw_complex*>(fftC_), - FFTW_MEASURE); - - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - - // alternative choice of plan type -// plan_c2r_ = -// fftw_plan_dft_1d(nsteps_, fftC_, fftR_, FFTW_BACKWARD, FFTW_MEASURE); -// plan_r2c_ = -// fftw_plan_dft_1d(nsteps_, fftR_, fftC_, FFTW_FORWARD, FFTW_MEASURE); - - ////////////////////////////////////////////////////////////////////////////// - // EXECUTION - // generate random physical data - for(unsigned int s=0; s<nsteps_; ++s) - fftR_[s] = FReal(rand())/FRandMax; - -// // display data in physical space -// std::cout<< "Physical data: "<<std::endl; -// for(unsigned int s=0; s<nsteps_; ++s) -// std::cout<< fftR_[s] << ", "; -// std::cout<<std::endl; - - // perform fft - std::cout<< "Perform Forward FFT: "; - time.tic(); - fftw_execute( plan_r2c_ ); - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - -// // display transform in Fourier space -// // beware the real data FFT stores only N/2+1 complex output values -// std::cout<< "Transformed data : "<<std::endl; -// for(unsigned int s=0; s<nsteps_; ++s) -// std::cout<< fftC_[s] << ", "; -// std::cout<<std::endl; - -// for(unsigned int s=0; s<nsteps_/2+1; ++s){ -// fftC_[nsteps_-s]=FComplex(fftC_[s].getReal(),-fftC_[s].getImag()); -// } -// -// std::cout<< "Full Transformed data : "<<std::endl; -// for(unsigned int s=0; s<nsteps_; ++s) -// std::cout<< fftC_[s] << ", "; -// std::cout<<std::endl; - - // perform ifft of tranformed data (in order to get physical values back) - std::cout<< "Perform Backward FFT: "; - time.tic(); - fftw_execute( plan_c2r_ ); - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - -// // display data in physical space -// std::cout<< "Physical data (from 1/N*IFFT(FFT(Physical data))): "<<std::endl; -// for(unsigned int s=0; s<nsteps_; ++s) -// std::cout<< fftR_[s]/nsteps_ << ", "; -// std::cout<<std::endl; - - ////////////////////////////////////////////////////////////////////////////// - // VALIDATION - // TODO - - //free memory - fftw_destroy_plan(plan_r2c_); - fftw_destroy_plan(plan_c2r_); - fftw_free(fftR_); - fftw_free(fftC_); + FHelpDescribeAndExit(argc, argv, "Test the FFTw (only the code is interesting)."); + + const FReal FRandMax = FReal(RAND_MAX); + + FTic time; + + ////////////////////////////////////////////////////////////////////////////// + // INITIALIZATION + + // size (pick a power of 2 for better performance of the FFT algorithm) + unsigned int nsteps_ = 500; + + // fftw arrays + FReal* fftR_; + FComplex* fftC_; + + fftR_ = (FReal*) fftw_malloc(sizeof(FReal) * nsteps_); + fftC_ = (FComplex*) fftw_malloc(sizeof(FComplex) * nsteps_); + + // fftw plans + // use routine defined in file: + // /PATH/TO/mkl/interfaces/fftw3xf/wrappers/fftw_plan_dft_c2r_1d.c + fftw_plan plan_c2r_; // backward FFT plan + fftw_plan plan_r2c_; // forward FFT plan + + std::cout<< "Init FFTW plans: "; + time.tic(); + + plan_c2r_ = + fftw_plan_dft_c2r_1d(nsteps_, + reinterpret_cast<fftw_complex*>(fftC_), + fftR_, + FFTW_MEASURE); + plan_r2c_ = + fftw_plan_dft_r2c_1d(nsteps_, + fftR_, + reinterpret_cast<fftw_complex*>(fftC_), + FFTW_MEASURE); + + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + + // alternative choice of plan type + // plan_c2r_ = + // fftw_plan_dft_1d(nsteps_, fftC_, fftR_, FFTW_BACKWARD, FFTW_MEASURE); + // plan_r2c_ = + // fftw_plan_dft_1d(nsteps_, fftR_, fftC_, FFTW_FORWARD, FFTW_MEASURE); + + ////////////////////////////////////////////////////////////////////////////// + // EXECUTION + // generate random physical data + for(unsigned int s=0; s<nsteps_; ++s) + fftR_[s] = FReal(rand())/FRandMax; + + // // display data in physical space + // std::cout<< "Physical data: "<<std::endl; + // for(unsigned int s=0; s<nsteps_; ++s) + // std::cout<< fftR_[s] << ", "; + // std::cout<<std::endl; + + // perform fft + std::cout<< "Perform Forward FFT: "; + time.tic(); + fftw_execute( plan_r2c_ ); + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + + // // display transform in Fourier space + // // beware the real data FFT stores only N/2+1 complex output values + // std::cout<< "Transformed data : "<<std::endl; + // for(unsigned int s=0; s<nsteps_; ++s) + // std::cout<< fftC_[s] << ", "; + // std::cout<<std::endl; + + // for(unsigned int s=0; s<nsteps_/2+1; ++s){ + // fftC_[nsteps_-s]=FComplex(fftC_[s].getReal(),-fftC_[s].getImag()); + // } + // + // std::cout<< "Full Transformed data : "<<std::endl; + // for(unsigned int s=0; s<nsteps_; ++s) + // std::cout<< fftC_[s] << ", "; + // std::cout<<std::endl; + + // perform ifft of tranformed data (in order to get physical values back) + std::cout<< "Perform Backward FFT: "; + time.tic(); + fftw_execute( plan_c2r_ ); + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + + // // display data in physical space + // std::cout<< "Physical data (from 1/N*IFFT(FFT(Physical data))): "<<std::endl; + // for(unsigned int s=0; s<nsteps_; ++s) + // std::cout<< fftR_[s]/nsteps_ << ", "; + // std::cout<<std::endl; + + ////////////////////////////////////////////////////////////////////////////// + // VALIDATION + // TODO + + //free memory + fftw_destroy_plan(plan_r2c_); + fftw_destroy_plan(plan_c2r_); + fftw_free(fftR_); + fftw_free(fftC_); }// end test diff --git a/Tests/Utils/testFFTWMultidim.cpp b/Tests/Utils/testFFTWMultidim.cpp index 85559e2738c417f54fa50ac5564bfc9a419a7e50..d7e01c1fcffa41f0accd5b3251df68277d3e9260 100644 --- a/Tests/Utils/testFFTWMultidim.cpp +++ b/Tests/Utils/testFFTWMultidim.cpp @@ -27,122 +27,124 @@ #include "../../Src/Utils/FComplex.hpp" #include "../../Src/Utils/FTic.hpp" - +#include "../../Src/Utils/FParameterNames.hpp" //#include "../../Src/Utils/FDft.hpp" -int main() +int main(int argc, char** argv) { - const FReal FRandMax = FReal(RAND_MAX); - - FTic time; - - ////////////////////////////////////////////////////////////////////////////// - // INITIALIZATION - // size (pick a power of 2 for better performance of the FFT algorithm) - const int dim=2; - const int pow_nsteps_=8; - int steps_[dim]; - int nsteps_=1; - for(int d=0; d<dim; ++d) { - steps_[d]=FMath::pow(2,pow_nsteps_); - nsteps_*=steps_[d]; - } - ////////////////////////////////////////////////////////////////////////////// - // Multidimensionnal FFT PLANS - std::cout<< "Test "<< dim <<"D FFT."<<std::endl; - // fftw arrays - FReal* fftR_; - FComplex* fftC_; - - fftR_ = (FReal*) fftw_malloc(sizeof(FReal) * nsteps_ ); - fftC_ = (FComplex*) fftw_malloc(sizeof(FComplex) * nsteps_ ); - - // fftw plans - // use routine defined in file: - // /PATH/TO/mkl/interfaces/fftw3xf/wrappers/fftw_plan_dft_c2r_1d.c - fftw_plan plan_c2r_; // backward FFT plan - fftw_plan plan_r2c_; // forward FFT plan - - std::cout<< "Init FFTW plans: "; - time.tic(); - - plan_c2r_ = - fftw_plan_dft_c2r(dim, steps_, - reinterpret_cast<fftw_complex*>(fftC_), - fftR_, - FFTW_MEASURE); - plan_r2c_ = - fftw_plan_dft_r2c(dim, steps_, - fftR_, - reinterpret_cast<fftw_complex*>(fftC_), - FFTW_MEASURE); - - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - - ////////////////////////////////////////////////////////////////////////////// - // EXECUTION - // generate random physical data - for(int s=0; s<nsteps_; ++s) - fftR_[s] = FReal(rand())/FRandMax; - -// // display data in physical space -// std::cout<< "Physical data: "<<std::endl; -// for( int r=0; r<steps_[0]; ++r) { -// for( int s=0; s<steps_[1]; ++s) -// std::cout<< fftR_[r*steps_[1]+s] << ", "; -// std::cout<<std::endl; -// } -// std::cout<<std::endl; - - // perform fft - std::cout<< "Perform Forward FFT: "; - time.tic(); - fftw_execute( plan_r2c_ ); - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - -// // display transform in Fourier space -// // beware the real data FFT stores only N/2+1 complex output values -// std::cout<< "Transformed data : "<<std::endl; -// for( int r=0; r<steps_[0]/2+1; ++r) { -// for( int s=0; s<steps_[1]/2+1; ++s) -// std::cout<< fftC_[r*(steps_[1]/2+1)+s] << ", "; -// std::cout<<std::endl; -// } -// std::cout<<std::endl; - -//// for( int s=0; s<steps_[1]/2+1; ++s){ -//// fftC_[nsteps_-s]=FComplex(fftC_[s].getReal(),-fftC_[s].getImag()); -//// } - -// std::cout<< "Full Transformed data : "<<std::endl; -// for( int r=0; r<steps_[0]; ++r){ -// for( int s=0; s<steps_[1]; ++s) -// std::cout<< fftC_[r*steps_[1]+s] << ", "; -// std::cout<<std::endl; -// } -// std::cout<<std::endl; - - // perform ifft of tranformed data (in order to get physical values back) - std::cout<< "Perform Backward FFT: "; - time.tic(); - fftw_execute( plan_c2r_ ); - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - -// // display data in physical space -// std::cout<< "Physical data (from 1/N*IFFT(FFT(Physical data))): "<<std::endl; -// for( int r=0; r<steps_[0]; ++r) { -// for( int s=0; s<steps_[1]; ++s) -// std::cout<< fftR_[r*steps_[1]+s]/(nsteps_) << ", "; -// std::cout<<std::endl; -// } -// std::cout<<std::endl; - - //free memory - fftw_destroy_plan(plan_r2c_); - fftw_destroy_plan(plan_c2r_); - fftw_free(fftR_); - fftw_free(fftC_); + FHelpDescribeAndExit(argc, argv, "Test the FFT in multi dimensions (only the code is interesting)."); + + const FReal FRandMax = FReal(RAND_MAX); + + FTic time; + + ////////////////////////////////////////////////////////////////////////////// + // INITIALIZATION + // size (pick a power of 2 for better performance of the FFT algorithm) + const int dim=2; + const int pow_nsteps_=8; + int steps_[dim]; + int nsteps_=1; + for(int d=0; d<dim; ++d) { + steps_[d]=FMath::pow(2,pow_nsteps_); + nsteps_*=steps_[d]; + } + ////////////////////////////////////////////////////////////////////////////// + // Multidimensionnal FFT PLANS + std::cout<< "Test "<< dim <<"D FFT."<<std::endl; + // fftw arrays + FReal* fftR_; + FComplex* fftC_; + + fftR_ = (FReal*) fftw_malloc(sizeof(FReal) * nsteps_ ); + fftC_ = (FComplex*) fftw_malloc(sizeof(FComplex) * nsteps_ ); + + // fftw plans + // use routine defined in file: + // /PATH/TO/mkl/interfaces/fftw3xf/wrappers/fftw_plan_dft_c2r_1d.c + fftw_plan plan_c2r_; // backward FFT plan + fftw_plan plan_r2c_; // forward FFT plan + + std::cout<< "Init FFTW plans: "; + time.tic(); + + plan_c2r_ = + fftw_plan_dft_c2r(dim, steps_, + reinterpret_cast<fftw_complex*>(fftC_), + fftR_, + FFTW_MEASURE); + plan_r2c_ = + fftw_plan_dft_r2c(dim, steps_, + fftR_, + reinterpret_cast<fftw_complex*>(fftC_), + FFTW_MEASURE); + + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + + ////////////////////////////////////////////////////////////////////////////// + // EXECUTION + // generate random physical data + for(int s=0; s<nsteps_; ++s) + fftR_[s] = FReal(rand())/FRandMax; + + // // display data in physical space + // std::cout<< "Physical data: "<<std::endl; + // for( int r=0; r<steps_[0]; ++r) { + // for( int s=0; s<steps_[1]; ++s) + // std::cout<< fftR_[r*steps_[1]+s] << ", "; + // std::cout<<std::endl; + // } + // std::cout<<std::endl; + + // perform fft + std::cout<< "Perform Forward FFT: "; + time.tic(); + fftw_execute( plan_r2c_ ); + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + + // // display transform in Fourier space + // // beware the real data FFT stores only N/2+1 complex output values + // std::cout<< "Transformed data : "<<std::endl; + // for( int r=0; r<steps_[0]/2+1; ++r) { + // for( int s=0; s<steps_[1]/2+1; ++s) + // std::cout<< fftC_[r*(steps_[1]/2+1)+s] << ", "; + // std::cout<<std::endl; + // } + // std::cout<<std::endl; + + //// for( int s=0; s<steps_[1]/2+1; ++s){ + //// fftC_[nsteps_-s]=FComplex(fftC_[s].getReal(),-fftC_[s].getImag()); + //// } + + // std::cout<< "Full Transformed data : "<<std::endl; + // for( int r=0; r<steps_[0]; ++r){ + // for( int s=0; s<steps_[1]; ++s) + // std::cout<< fftC_[r*steps_[1]+s] << ", "; + // std::cout<<std::endl; + // } + // std::cout<<std::endl; + + // perform ifft of tranformed data (in order to get physical values back) + std::cout<< "Perform Backward FFT: "; + time.tic(); + fftw_execute( plan_c2r_ ); + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + + // // display data in physical space + // std::cout<< "Physical data (from 1/N*IFFT(FFT(Physical data))): "<<std::endl; + // for( int r=0; r<steps_[0]; ++r) { + // for( int s=0; s<steps_[1]; ++s) + // std::cout<< fftR_[r*steps_[1]+s]/(nsteps_) << ", "; + // std::cout<<std::endl; + // } + // std::cout<<std::endl; + + //free memory + fftw_destroy_plan(plan_r2c_); + fftw_destroy_plan(plan_c2r_); + fftw_free(fftR_); + fftw_free(fftC_); }// end test diff --git a/Tests/Utils/testFastDiscreteConvolution.cpp b/Tests/Utils/testFastDiscreteConvolution.cpp index b63e685a0e1cbf3357a432debc9993d472be229b..1d7fc99c7d761aa2db37aaeb434fc18572a94abd 100644 --- a/Tests/Utils/testFastDiscreteConvolution.cpp +++ b/Tests/Utils/testFastDiscreteConvolution.cpp @@ -33,151 +33,149 @@ #include "../../Src/Utils/FDft.hpp" #include "../../Src/Utils/FComplex.hpp" +#include "../../Src/Utils/FParameterNames.hpp" -/** - * In this file we show how to use octree - */ +int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, "Test the FFT (only the code is interesting)."); -int main(int, char **){ + const FReal FRandMax = FReal(RAND_MAX); - const FReal FRandMax = FReal(RAND_MAX); + FTic time; - FTic time; + const unsigned int ORDER = 3; + const unsigned int N=(2*ORDER-1); - const unsigned int ORDER = 3; - const unsigned int N=(2*ORDER-1); + ////////////////////////////////////////////////////////////////////////////// + // Application of Convolution Theorem + // Let there be a Circulant Toeplitz matrix K of size N - ////////////////////////////////////////////////////////////////////////////// - // Application of Convolution Theorem - // Let there be a Circulant Toeplitz matrix K of size N + FReal K[N*N]; + FReal Y[N]; + FReal X[N]; - FReal K[N*N]; - FReal Y[N]; - FReal X[N]; + for(unsigned int i=0; i<N; ++i) X[i]=0.0; + for(unsigned int i=0; i<N; ++i) Y[i]=FReal(rand())/FRandMax; - for(unsigned int i=0; i<N; ++i) X[i]=0.0; - for(unsigned int i=0; i<N; ++i) Y[i]=FReal(rand())/FRandMax; + std::cout<< "Y: "<<std::endl; + for(unsigned int i=0; i<N; ++i) + std::cout<< Y[i] << ", "; + std::cout<<std::endl; - std::cout<< "Y: "<<std::endl; - for(unsigned int i=0; i<N; ++i) - std::cout<< Y[i] << ", "; - std::cout<<std::endl; - - // Assemble Matrix K - std::cout<< "Assemble Full Matrix K: "; - time.tic(); - for(unsigned int i=0; i<N; ++i){ - for(unsigned int j=0; j<N; ++j){ - if(i>j) K[i*N+j]=i-j-1; - else K[i*N+j]=N+i-j-1; + // Assemble Matrix K + std::cout<< "Assemble Full Matrix K: "; + time.tic(); + for(unsigned int i=0; i<N; ++i){ + for(unsigned int j=0; j<N; ++j){ + if(i>j) K[i*N+j]=i-j-1; + else K[i*N+j]=N+i-j-1; + } } - } - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - std::cout<< "Circulant Toeplitz matrix K: "<<std::endl; - for(unsigned int i=0; i<N; ++i){ - for(unsigned int j=0; j<N; ++j){ - std::cout<< K[i*N+j] << ", "; + std::cout<< "Circulant Toeplitz matrix K: "<<std::endl; + for(unsigned int i=0; i<N; ++i){ + for(unsigned int j=0; j<N; ++j){ + std::cout<< K[i*N+j] << ", "; + } std::cout<<std::endl; } std::cout<<std::endl; - } std::cout<<std::endl; - - // Direct application of Circulant Matrix - std::cout<< "Direct application of K: "; - time.tic(); - for(unsigned int i=0; i<N; ++i){ - for(unsigned int j=0; j<N; ++j){ - X[i]+=K[i*N+j]*Y[j]; + + // Direct application of Circulant Matrix + std::cout<< "Direct application of K: "; + time.tic(); + for(unsigned int i=0; i<N; ++i){ + for(unsigned int j=0; j<N; ++j){ + X[i]+=K[i*N+j]*Y[j]; + } + } + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + + std::cout<< "X=KY: "<<std::endl; + for(unsigned int i=0; i<N; ++i) + std::cout<< X[i] << ", "; + std::cout<<std::endl; + + // now compute via DFT and use convolution theorem + FComplex FK[N]; + FComplex FY[N]; + FComplex FX[N]; + FReal iFX[N]; + + // Init DFTor + std::cout<< "Set DFT: "; + time.tic(); + const int dim = 1; + const int steps[dim] = {N}; + //FDft<FReal> Dft(N);// direct version (Beware! Ordering of output differs from REAL valued-FFT) + FFft<dim> Dft;// fast version + Dft.buildDFT(steps);// fast version + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + + // Initialize manually + // for(unsigned int s=0; s<N; ++s){ + // FX[s] = FY[s] = FK[s] =FComplex(0.0,0.0); // init + // iFX[s]=0.0; + // } + // ... or using Blas routines + FBlas::c_setzero(N,reinterpret_cast<FReal*>(FX)); + FBlas::c_setzero(N,reinterpret_cast<FReal*>(FY)); + FBlas::c_setzero(N,reinterpret_cast<FReal*>(FK)); + FBlas::setzero(N,iFX); + + + // Transform Y in Fourier space + std::cout<< "Transform Y->FY: "; + time.tic(); + Dft.applyDFT(Y,FY); + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + + std::cout<< "FY: "<<std::endl; + for(unsigned int i=0; i<N; ++i){ + std::cout<< FY[i] << ", "; + }std::cout<<std::endl; + + // Transform first column of K + FReal tK[N]; + for(unsigned int i=0; i<N; ++i) tK[i]=K[i*N]; // first column + // for(unsigned int i=0; i<N; ++i) tK[i]=K[i]; // first row + std::cout<< "Transform tK->FK: "; + time.tic(); + Dft.applyDFT(tK,FK); + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + + // std::cout<< "Transformed Matrix FK: "<<std::endl; + // for(unsigned int i=0; i<N; ++i){ + // std::cout<< FK[i] << ", "; + // }std::cout<<std::endl; + + // Compute X=KY in Fourier space + std::cout<< "Apply K in Fourier space (entrywise prod.): "; + time.tic(); + for(unsigned int s=0; s<N; ++s){// TODO loop only over non zero entries + FX[s]=FK[s]; + FX[s]*=FY[s]; } - } - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - - std::cout<< "X=KY: "<<std::endl; - for(unsigned int i=0; i<N; ++i) - std::cout<< X[i] << ", "; - std::cout<<std::endl; - - // now compute via DFT and use convolution theorem - FComplex FK[N]; - FComplex FY[N]; - FComplex FX[N]; - FReal iFX[N]; - - // Init DFTor - std::cout<< "Set DFT: "; - time.tic(); - const int dim = 1; - const int steps[dim] = {N}; - //FDft<FReal> Dft(N);// direct version (Beware! Ordering of output differs from REAL valued-FFT) - FFft<dim> Dft;// fast version - Dft.buildDFT(steps);// fast version - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - - // Initialize manually -// for(unsigned int s=0; s<N; ++s){ -// FX[s] = FY[s] = FK[s] =FComplex(0.0,0.0); // init -// iFX[s]=0.0; -// } - // ... or using Blas routines - FBlas::c_setzero(N,reinterpret_cast<FReal*>(FX)); - FBlas::c_setzero(N,reinterpret_cast<FReal*>(FY)); - FBlas::c_setzero(N,reinterpret_cast<FReal*>(FK)); - FBlas::setzero(N,iFX); - - - // Transform Y in Fourier space - std::cout<< "Transform Y->FY: "; - time.tic(); - Dft.applyDFT(Y,FY); - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - - std::cout<< "FY: "<<std::endl; - for(unsigned int i=0; i<N; ++i){ - std::cout<< FY[i] << ", "; - }std::cout<<std::endl; - - // Transform first column of K - FReal tK[N]; - for(unsigned int i=0; i<N; ++i) tK[i]=K[i*N]; // first column -// for(unsigned int i=0; i<N; ++i) tK[i]=K[i]; // first row - std::cout<< "Transform tK->FK: "; - time.tic(); - Dft.applyDFT(tK,FK); - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - -// std::cout<< "Transformed Matrix FK: "<<std::endl; -// for(unsigned int i=0; i<N; ++i){ -// std::cout<< FK[i] << ", "; -// }std::cout<<std::endl; - - // Compute X=KY in Fourier space - std::cout<< "Apply K in Fourier space (entrywise prod.): "; - time.tic(); - for(unsigned int s=0; s<N; ++s){// TODO loop only over non zero entries - FX[s]=FK[s]; - FX[s]*=FY[s]; - } - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - - std::cout<< "Transformed Local Exp FX=FK:FY: "<<std::endl; - for(unsigned int i=0; i<N; ++i){ - std::cout<< FX[i] << ", "; - }std::cout<<std::endl; - - // Transform FX back in Physical space - std::cout<< "Transform FX->iF(FX): "; - time.tic(); - Dft.applyIDFT(FX,iFX); - std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; - - std::cout<< "iF(FK:FY): "<<std::endl; - for(unsigned int i=0; i<N; ++i){ - std::cout<< iFX[i] << ", "; - }std::cout<<std::endl; - -std::cout << "Relative error = " << FMath::FAccurater( X, iFX, N) << std::endl; - - - return 0; + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + + std::cout<< "Transformed Local Exp FX=FK:FY: "<<std::endl; + for(unsigned int i=0; i<N; ++i){ + std::cout<< FX[i] << ", "; + }std::cout<<std::endl; + + // Transform FX back in Physical space + std::cout<< "Transform FX->iF(FX): "; + time.tic(); + Dft.applyIDFT(FX,iFX); + std::cout << "took " << time.tacAndElapsed() << "sec." << std::endl; + + std::cout<< "iF(FK:FY): "<<std::endl; + for(unsigned int i=0; i<N; ++i){ + std::cout<< iFX[i] << ", "; + }std::cout<<std::endl; + + std::cout << "Relative error = " << FMath::FAccurater( X, iFX, N) << std::endl; + + + return 0; } diff --git a/Tests/Utils/testFmmAlgorithm.cpp b/Tests/Utils/testFmmAlgorithm.cpp index b33692f78957bfab9bb7c8c1546e8e0d5f6c2ee5..e4fc15382864c790b0a3916a8c166fc519dc9551 100755 --- a/Tests/Utils/testFmmAlgorithm.cpp +++ b/Tests/Utils/testFmmAlgorithm.cpp @@ -40,6 +40,7 @@ #include "../../Src/Files/FRandomLoader.hpp" +#include "../../Src/Utils/FParameterNames.hpp" /** This program show an example of use of the fmm basic algo * it also check that each particles is impacted each other particles @@ -47,6 +48,11 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Test FMM algorithm by counting the nb of interactions each particle receive.", + FParameterDefinitions::OctreeHeight, FParameterDefinitions::OctreeSubHeight, + FParameterDefinitions::NbParticles); + typedef FTestCell CellClass; typedef FTestParticleContainer ContainerClass; @@ -61,9 +67,9 @@ 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,"-h", 7); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); - const int NbPart = FParameters::getValue(argc,argv,"-nb", 2000000); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 7); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); + const int NbPart = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 2000000); FTic counter; ////////////////////////////////////////////////////////////////////////////////// diff --git a/Tests/Utils/testFmmAlgorithmPeriodic.cpp b/Tests/Utils/testFmmAlgorithmPeriodic.cpp index 99ad8e796a521d6063f002feb801bb1bf0cd03ae..4745d77b25b6b636ea835f391f6516b01c19a020 100755 --- a/Tests/Utils/testFmmAlgorithmPeriodic.cpp +++ b/Tests/Utils/testFmmAlgorithmPeriodic.cpp @@ -41,6 +41,8 @@ #include "../../Src/Core/FFmmAlgorithmPeriodic.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that each particles is impacted each other particles @@ -49,6 +51,12 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Test FMM periodic algorithm by counting the nb of interactions each particle receive.", + FParameterDefinitions::OctreeHeight, FParameterDefinitions::OctreeSubHeight, + FParameterDefinitions::NbParticles, FParameterDefinitions::PeriodicityNbLevels); + + typedef FTestCell CellClass; typedef FTestParticleContainer ContainerClass; @@ -61,10 +69,10 @@ 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,"-h", 5); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); - const long NbParticles = FParameters::getValue(argc,argv,"-nb", 1000); - const int PeriodicDeep = FParameters::getValue(argc,argv,"-per", 2); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); + const long NbParticles = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 1000); + const int PeriodicDeep = FParameters::getValue(argc,argv,FParameterDefinitions::PeriodicityNbLevels.options, 2); // choose in +x dir or -/+x dir or all dirs FTic counter; diff --git a/Tests/Utils/testFmmAlgorithmProc.cpp b/Tests/Utils/testFmmAlgorithmProc.cpp index 227dd8767fe4352502126a109384523609c0a80b..6223cdbcdf78dced124293580e7568a48c6e5b99 100755 --- a/Tests/Utils/testFmmAlgorithmProc.cpp +++ b/Tests/Utils/testFmmAlgorithmProc.cpp @@ -45,6 +45,8 @@ #include "../../Src/BalanceTree/FLeafBalance.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + #include <iostream> #include <cstdio> #include <cstdlib> @@ -304,19 +306,23 @@ typedef FFmmAlgorithmThreadProc<OctreeClass, CellClass, ContainerClass, KernelCl // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Test FMM distributed algorithm by counting the nb of interactions each particle receive.", + FParameterDefinitions::OctreeHeight, FParameterDefinitions::OctreeSubHeight, + FParameterDefinitions::InputFile); ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test the FMM algorithm.\n"; ////////////////////////////////////////////////////////////// FMpi app( argc, argv); - const int NbLevels = FParameters::getValue(argc,argv,"-h", 5); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 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 char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, defaultFilename); std::cout << "Opening : " << filename << "\n"; std::ifstream loader; diff --git a/Tests/Utils/testFmmAlgorithmProcPeriodic.cpp b/Tests/Utils/testFmmAlgorithmProcPeriodic.cpp index 7f7f654e49227d1404759b5fb85573b8ad84c68f..212bb211638e13178f055d1b345c45ac5eccfe28 100755 --- a/Tests/Utils/testFmmAlgorithmProcPeriodic.cpp +++ b/Tests/Utils/testFmmAlgorithmProcPeriodic.cpp @@ -45,6 +45,8 @@ #include "../../Src/BalanceTree/FLeafBalance.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that each particles is impacted each other particles @@ -53,6 +55,12 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Test FMM periodic distributed algorithm by counting the nb of interactions each particle receive.", + FParameterDefinitions::OctreeHeight, FParameterDefinitions::OctreeSubHeight, + FParameterDefinitions::NbParticles); + + typedef FTestCell CellClass; typedef FTestParticleContainer ContainerClass; @@ -66,9 +74,9 @@ 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,"-h", 7); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); - const long NbParticles = FParameters::getValue(argc,argv,"-nb", 5); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 7); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); + const long NbParticles = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 5); const int PeriodicDeep = FParameters::getValue(argc,argv,"-per", 2); diff --git a/Tests/Utils/testFmmAlgorithmProcRotation.cpp b/Tests/Utils/testFmmAlgorithmProcRotation.cpp index 6b766267f87eee18c554b58e12ab242c29db7669..d568743990251342c742dd4d0293de73f46f2789 100644 --- a/Tests/Utils/testFmmAlgorithmProcRotation.cpp +++ b/Tests/Utils/testFmmAlgorithmProcRotation.cpp @@ -43,6 +43,8 @@ #include "BalanceTree/FLeafBalance.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + #include <iostream> #include <cstdio> @@ -67,357 +69,361 @@ static const FReal Epsilon = FReal(0.00005); /** To compare data */ template <class CellClass> bool isEqualPole(const CellClass& me, const CellClass& other, FReal*const cumul){ - FMath::FAccurater accurate; - for(int idx = 0; idx < me.getArraySize(); ++idx){ - accurate.add(me.getMultipole()[idx].getImag(),other.getMultipole()[idx].getImag()); - accurate.add(me.getMultipole()[idx].getReal(),other.getMultipole()[idx].getReal()); - } - *cumul = accurate.getInfNorm()+ accurate.getL2Norm(); - return accurate.getInfNorm() < Epsilon && accurate.getL2Norm() < Epsilon;//FMath::LookEqual(cumul,FReal(0.0)); + FMath::FAccurater accurate; + for(int idx = 0; idx < me.getArraySize(); ++idx){ + accurate.add(me.getMultipole()[idx].getImag(),other.getMultipole()[idx].getImag()); + accurate.add(me.getMultipole()[idx].getReal(),other.getMultipole()[idx].getReal()); + } + *cumul = accurate.getInfNorm()+ accurate.getL2Norm(); + return accurate.getInfNorm() < Epsilon && accurate.getL2Norm() < Epsilon;//FMath::LookEqual(cumul,FReal(0.0)); } /** To compare data */ bool isEqualLocal(const FRotationCell<7>& me, const FRotationCell<7>& other, FReal*const cumul){ - FMath::FAccurater accurate; - for(int idx = 0; idx < me.getArraySize(); ++idx){ - accurate.add(me.getLocal()[idx].getImag(),other.getLocal()[idx].getImag()); - accurate.add(me.getLocal()[idx].getReal(),other.getLocal()[idx].getReal()); - } - *cumul = accurate.getInfNorm()+ accurate.getL2Norm(); - return accurate.getInfNorm() < Epsilon && accurate.getL2Norm() < Epsilon;//FMath::LookEqual(cumul,FReal(0.0)); + FMath::FAccurater accurate; + for(int idx = 0; idx < me.getArraySize(); ++idx){ + accurate.add(me.getLocal()[idx].getImag(),other.getLocal()[idx].getImag()); + accurate.add(me.getLocal()[idx].getReal(),other.getLocal()[idx].getReal()); + } + *cumul = accurate.getInfNorm()+ accurate.getL2Norm(); + return accurate.getInfNorm() < Epsilon && accurate.getL2Norm() < Epsilon;//FMath::LookEqual(cumul,FReal(0.0)); } template<class OctreeClass, class ContainerClass> void ValidateFMMAlgoProc(OctreeClass* const badTree, - OctreeClass* const valideTree, - FMpi * const app){ - std::cout << "Check Result\n"; - { - const int OctreeHeight = valideTree->getHeight(); - typename OctreeClass::Iterator octreeIterator(badTree); - octreeIterator.gotoBottomLeft(); - - typename OctreeClass::Iterator octreeIteratorValide(valideTree); - octreeIteratorValide.gotoBottomLeft(); - - for(int level = OctreeHeight - 1 ; level > 1 ; --level){ - while(octreeIteratorValide.getCurrentGlobalIndex() != octreeIterator.getCurrentGlobalIndex()){ - octreeIteratorValide.moveRight(); - } - - do { - if(octreeIterator.getCurrentGlobalIndex() != octreeIteratorValide.getCurrentGlobalIndex()){ - std::cout << "Error index are not equal!" << std::endl; - } - else{ - FReal cumul; - if( !isEqualPole(*octreeIterator.getCurrentCell(),*octreeIteratorValide.getCurrentCell(),&cumul) ){ - std::cout << "Pole Data are different for proc "<< app->global().processId() <<" Cumul " << cumul << " at level " << level << " index is " << octreeIterator.getCurrentGlobalIndex() << std::endl; - } - if( !isEqualLocal(*octreeIterator.getCurrentCell(),*octreeIteratorValide.getCurrentCell(),&cumul) ){ - std::cout << "Local Data are different for proc "<< app->global().processId() <<" Cumul " << cumul << " at level " << level << " index is " << octreeIterator.getCurrentGlobalIndex() << std::endl; - } - } - - } while(octreeIterator.moveRight() && octreeIteratorValide.moveRight()); - - octreeIterator.moveUp(); - octreeIterator.gotoLeft(); - - octreeIteratorValide.moveUp(); - octreeIteratorValide.gotoLeft(); + OctreeClass* const valideTree, + FMpi * const app){ + std::cout << "Check Result\n"; + { + const int OctreeHeight = valideTree->getHeight(); + typename OctreeClass::Iterator octreeIterator(badTree); + octreeIterator.gotoBottomLeft(); + + typename OctreeClass::Iterator octreeIteratorValide(valideTree); + octreeIteratorValide.gotoBottomLeft(); + + for(int level = OctreeHeight - 1 ; level > 1 ; --level){ + while(octreeIteratorValide.getCurrentGlobalIndex() != octreeIterator.getCurrentGlobalIndex()){ + octreeIteratorValide.moveRight(); + } + + do { + if(octreeIterator.getCurrentGlobalIndex() != octreeIteratorValide.getCurrentGlobalIndex()){ + std::cout << "Error index are not equal!" << std::endl; + } + else{ + FReal cumul; + if( !isEqualPole(*octreeIterator.getCurrentCell(),*octreeIteratorValide.getCurrentCell(),&cumul) ){ + std::cout << "Pole Data are different for proc "<< app->global().processId() <<" Cumul " << cumul << " at level " << level << " index is " << octreeIterator.getCurrentGlobalIndex() << std::endl; + } + if( !isEqualLocal(*octreeIterator.getCurrentCell(),*octreeIteratorValide.getCurrentCell(),&cumul) ){ + std::cout << "Local Data are different for proc "<< app->global().processId() <<" Cumul " << cumul << " at level " << level << " index is " << octreeIterator.getCurrentGlobalIndex() << std::endl; + } + } + + } while(octreeIterator.moveRight() && octreeIteratorValide.moveRight()); + + octreeIterator.moveUp(); + octreeIterator.gotoLeft(); + + octreeIteratorValide.moveUp(); + octreeIteratorValide.gotoLeft(); + } } - } - { - // Check that each particle has been summed with all other - typename OctreeClass::Iterator octreeIterator(badTree); - octreeIterator.gotoBottomLeft(); - - typename OctreeClass::Iterator octreeIteratorValide(valideTree); - octreeIteratorValide.gotoBottomLeft(); - - while(octreeIteratorValide.getCurrentGlobalIndex() != octreeIterator.getCurrentGlobalIndex()){ - octreeIteratorValide.moveRight(); + { + // Check that each particle has been summed with all other + typename OctreeClass::Iterator octreeIterator(badTree); + octreeIterator.gotoBottomLeft(); + + typename OctreeClass::Iterator octreeIteratorValide(valideTree); + octreeIteratorValide.gotoBottomLeft(); + + while(octreeIteratorValide.getCurrentGlobalIndex() != octreeIterator.getCurrentGlobalIndex()){ + octreeIteratorValide.moveRight(); + } + + do { + + if( octreeIterator.getCurrentListSrc()->getNbParticles() != octreeIteratorValide.getCurrentListSrc()->getNbParticles()){ + std::cout << " Particules numbers is different " << std::endl; + } + if( octreeIterator.getCurrentGlobalIndex() != octreeIteratorValide.getCurrentGlobalIndex()){ + std::cout << " Index are differents " << std::endl; + } + + ContainerClass* firstLeaf = octreeIterator.getCurrentListTargets(); + ContainerClass* valideLeaf = octreeIteratorValide.getCurrentListTargets(); + + const FReal*const potentials = firstLeaf->getPotentials(); + const FReal*const forcesX = firstLeaf->getForcesX(); + const FReal*const forcesY = firstLeaf->getForcesY(); + const FReal*const forcesZ = firstLeaf->getForcesZ(); + const FReal*const positionX = firstLeaf->getPositions()[0]; + const FReal*const positionY = firstLeaf->getPositions()[1]; + const FReal*const positionZ = firstLeaf->getPositions()[2]; + const FReal*const validePositionX = valideLeaf->getPositions()[0]; + const FReal*const validePositionY = valideLeaf->getPositions()[1]; + const FReal*const validePositionZ = valideLeaf->getPositions()[2]; + const FReal*const validePotentials = valideLeaf->getPotentials(); + const FReal*const valideForcesX = valideLeaf->getForcesX(); + const FReal*const valideForcesY = valideLeaf->getForcesY(); + const FReal*const valideForcesZ = valideLeaf->getForcesZ(); + + for(int idxLeaf = 0 ; idxLeaf < firstLeaf->getNbParticles() ; ++idxLeaf){ + + int idxValideLeaf = 0; + for(; idxValideLeaf < valideLeaf->getNbParticles() ; ++idxValideLeaf){ + if( FMath::LookEqual(validePositionX[idxValideLeaf],positionX[idxLeaf]) && + FMath::LookEqual(validePositionY[idxValideLeaf],positionY[idxLeaf]) && + FMath::LookEqual(validePositionZ[idxValideLeaf],positionZ[idxLeaf]) ){ + break; + } + } + + if( idxValideLeaf < valideLeaf->getNbParticles() ){ + // If a particles has been impacted by less than NbPart - 1 (the current particle) + // there is a problem + bool error = false; + if( FMath::RelatifDiff(validePotentials[idxValideLeaf] , potentials[idxLeaf]) > Epsilon ){ + std::cout << " Potential error : " << validePotentials[idxValideLeaf] << " " << potentials[idxLeaf] << "\n"; + error = true; + } + if( FMath::RelatifDiff(valideForcesX[idxValideLeaf],forcesX[idxLeaf]) > Epsilon + || FMath::RelatifDiff(valideForcesY[idxValideLeaf],forcesY[idxLeaf]) > Epsilon + || FMath::RelatifDiff(valideForcesZ[idxValideLeaf],forcesZ[idxLeaf]) > Epsilon){ + std::cout << " Forces error : x " << valideForcesX[idxValideLeaf] << " " << forcesX[idxLeaf] + << " y " << valideForcesY[idxValideLeaf] << " " << forcesY[idxLeaf] + << " z " << valideForcesZ[idxValideLeaf] << " " << forcesZ[idxLeaf] << "\n"; + error = true; + } + if( error ){ + std::cout << "At position " << FPoint(validePositionX[idxValideLeaf],validePositionY[idxValideLeaf],validePositionZ[idxValideLeaf]) + << " == " << FPoint(positionX[idxLeaf],positionY[idxLeaf],positionZ[idxLeaf]) << std::endl; + } + } + else{ + std::cout << "Particle not found " << FPoint(positionX[idxLeaf],positionY[idxLeaf],positionZ[idxLeaf]) << std::endl; + } + } + + } while(octreeIterator.moveRight() && octreeIteratorValide.moveRight()); } - do { - - if( octreeIterator.getCurrentListSrc()->getNbParticles() != octreeIteratorValide.getCurrentListSrc()->getNbParticles()){ - std::cout << " Particules numbers is different " << std::endl; - } - if( octreeIterator.getCurrentGlobalIndex() != octreeIteratorValide.getCurrentGlobalIndex()){ - std::cout << " Index are differents " << std::endl; - } - - ContainerClass* firstLeaf = octreeIterator.getCurrentListTargets(); - ContainerClass* valideLeaf = octreeIteratorValide.getCurrentListTargets(); - - const FReal*const potentials = firstLeaf->getPotentials(); - const FReal*const forcesX = firstLeaf->getForcesX(); - const FReal*const forcesY = firstLeaf->getForcesY(); - const FReal*const forcesZ = firstLeaf->getForcesZ(); - const FReal*const positionX = firstLeaf->getPositions()[0]; - const FReal*const positionY = firstLeaf->getPositions()[1]; - const FReal*const positionZ = firstLeaf->getPositions()[2]; - const FReal*const validePositionX = valideLeaf->getPositions()[0]; - const FReal*const validePositionY = valideLeaf->getPositions()[1]; - const FReal*const validePositionZ = valideLeaf->getPositions()[2]; - const FReal*const validePotentials = valideLeaf->getPotentials(); - const FReal*const valideForcesX = valideLeaf->getForcesX(); - const FReal*const valideForcesY = valideLeaf->getForcesY(); - const FReal*const valideForcesZ = valideLeaf->getForcesZ(); - - for(int idxLeaf = 0 ; idxLeaf < firstLeaf->getNbParticles() ; ++idxLeaf){ - - int idxValideLeaf = 0; - for(; idxValideLeaf < valideLeaf->getNbParticles() ; ++idxValideLeaf){ - if( FMath::LookEqual(validePositionX[idxValideLeaf],positionX[idxLeaf]) && - FMath::LookEqual(validePositionY[idxValideLeaf],positionY[idxLeaf]) && - FMath::LookEqual(validePositionZ[idxValideLeaf],positionZ[idxLeaf]) ){ - break; - } - } - - if( idxValideLeaf < valideLeaf->getNbParticles() ){ - // If a particles has been impacted by less than NbPart - 1 (the current particle) - // there is a problem - bool error = false; - if( FMath::RelatifDiff(validePotentials[idxValideLeaf] , potentials[idxLeaf]) > Epsilon ){ - std::cout << " Potential error : " << validePotentials[idxValideLeaf] << " " << potentials[idxLeaf] << "\n"; - error = true; - } - if( FMath::RelatifDiff(valideForcesX[idxValideLeaf],forcesX[idxLeaf]) > Epsilon - || FMath::RelatifDiff(valideForcesY[idxValideLeaf],forcesY[idxLeaf]) > Epsilon - || FMath::RelatifDiff(valideForcesZ[idxValideLeaf],forcesZ[idxLeaf]) > Epsilon){ - std::cout << " Forces error : x " << valideForcesX[idxValideLeaf] << " " << forcesX[idxLeaf] - << " y " << valideForcesY[idxValideLeaf] << " " << forcesY[idxLeaf] - << " z " << valideForcesZ[idxValideLeaf] << " " << forcesZ[idxLeaf] << "\n"; - error = true; - } - if( error ){ - std::cout << "At position " << FPoint(validePositionX[idxValideLeaf],validePositionY[idxValideLeaf],validePositionZ[idxValideLeaf]) - << " == " << FPoint(positionX[idxLeaf],positionY[idxLeaf],positionZ[idxLeaf]) << std::endl; - } - } - else{ - std::cout << "Particle not found " << FPoint(positionX[idxLeaf],positionY[idxLeaf],positionZ[idxLeaf]) << std::endl; - } - } - - } while(octreeIterator.moveRight() && octreeIteratorValide.moveRight()); - } - - std::cout << "Done\n"; + std::cout << "Done\n"; } #endif // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Test FMM distributed algorithm with the rotation kernel.", + FParameterDefinitions::OctreeHeight, FParameterDefinitions::OctreeSubHeight, + FParameterDefinitions::InputFile); - // For Rotation test :: - typedef FRotationCell<7> CellClass; - typedef FP2PParticleContainer<> ContainerClass; + // For Rotation test :: + typedef FRotationCell<7> CellClass; + typedef FP2PParticleContainer<> ContainerClass; - typedef FSimpleLeaf< ContainerClass > LeafClass; - typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FRotationKernel< CellClass, ContainerClass,7 > KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FRotationKernel< CellClass, ContainerClass,7 > KernelClass; - typedef FFmmAlgorithmThreadProc<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassNoProc; + 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 Proc Rotation algorithm.\n"; - ////////////////////////////////////////////////////////////// + ///////////////////////What we do///////////////////////////// + std::cout << ">> This executable has to be used to test Proc Rotation algorithm.\n"; + ////////////////////////////////////////////////////////////// - FMpi app( argc, argv); + FMpi app( argc, argv); - const int NbLevels = FParameters::getValue(argc,argv,"-h", 5); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 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 NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 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,FParameterDefinitions::InputFile.options, defaultFilename); - std::cout << "Opening : " << filename << "\n"; + std::cout << "Opening : " << filename << "\n"; - FMpiFmaGenericLoader loader(filename, app.global()); - if(!loader.isOpen()){ - std::cout << "Loader Error, " << filename << " is missing\n"; - return 1; - } - - // ----Modified For Rotation---------------------------- + FMpiFmaGenericLoader loader(filename, app.global()); + if(!loader.isOpen()){ + std::cout << "Loader Error, " << filename << " is missing\n"; + return 1; + } - OctreeClass tree(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); + // ----Modified For Rotation---------------------------- - // ----------------------------------------------------- + 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; + std::cout << "Creating & Inserting " << loader.getNumberOfParticles() << " particles ..." << std::endl; + std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - struct TestParticle{ - FPoint position; - FReal physicalValue; - const FPoint& getPosition(){ - return position; - } - }; - - TestParticle* particles = new TestParticle[loader.getNumberOfParticles()]; - memset(particles, 0, (unsigned int) (sizeof(TestParticle) * loader.getNumberOfParticles())); - - for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - loader.fillParticle(&particles[idxPart].position,&particles[idxPart].physicalValue); + 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, (unsigned int) (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; + + ////////////////////////////////////////////////////////////////////////////////// } - - 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); + else{ + FPoint position; + FReal physicalValue; + for(FSize idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&position,&physicalValue); + tree.insert(position, 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 << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; - // ----------------------------------------------------- - std::cout << "Create kernel..." << std::endl; - { - KernelClass kernels( NbLevels,loader.getBoxWidth(), loader.getCenterOfBox()); + // ----------------------------------------------------- + std::cout << "Create kernel..." << std::endl; + { + KernelClass kernels( NbLevels,loader.getBoxWidth(), loader.getCenterOfBox()); - std::cout << "Done " << " in " << counter.elapsed() << "s)." << std::endl; + std::cout << "Done " << " in " << counter.elapsed() << "s)." << std::endl; - // ----------------------------------------------------- + // ----------------------------------------------------- - std::cout << "Working on particles ..." << std::endl; - { - FmmClass algo(app.global(),&tree,&kernels); + std::cout << "Working on particles ..." << std::endl; + { + FmmClass algo(app.global(),&tree,&kernels); - counter.tic(); - algo.execute(FFmmM2M); - counter.tac(); + counter.tic(); + algo.execute(FFmmM2M); + counter.tac(); - std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl; + std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl; - { // get sum forces&potential + { // get sum forces&potential - FReal potential = 0; - FReal fx = 0.0, fy = 0.0, fz = 0.0; + 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(); + 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]; - } - }); + 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; + 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); + 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 << "Forces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; - std::cout << "Potential Sum = " << potential << std::endl; - } - } + if(app.global().processId() == 0){ + std::cout << "Forces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; + std::cout << "Potential Sum = " << potential << std::endl; + } + } #ifdef VALIDATE_FMM - { - OctreeClass treeValide(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); - { - FFmaGenericLoader loaderSeq(filename); - FPoint position; - FReal physicalValue; - for(FSize idxPart = 0 ; idxPart < loaderSeq.getNumberOfParticles() ; ++idxPart){ - loaderSeq.fillParticle(&position,&physicalValue); - treeValide.insert(position,physicalValue); - } - } - - std::cout << "Working on particles ..." << std::endl; - FmmClassNoProc algoValide(&treeValide,&kernels); - counter.tic(); - algoValide.execute(); - counter.tac(); - std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl; - - 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 << "Forces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; - std::cout << "Potential = " << potential << std::endl; - - ValidateFMMAlgoProc<OctreeClass,ContainerClass>(&tree,&treeValide,&app); - } + { + OctreeClass treeValide(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); + { + FFmaGenericLoader loaderSeq(filename); + FPoint position; + FReal physicalValue; + for(FSize idxPart = 0 ; idxPart < loaderSeq.getNumberOfParticles() ; ++idxPart){ + loaderSeq.fillParticle(&position,&physicalValue); + treeValide.insert(position,physicalValue); + } + } + + std::cout << "Working on particles ..." << std::endl; + FmmClassNoProc algoValide(&treeValide,&kernels); + counter.tic(); + algoValide.execute(); + counter.tac(); + std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl; + + 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 << "Forces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; + std::cout << "Potential = " << potential << std::endl; + + ValidateFMMAlgoProc<OctreeClass,ContainerClass>(&tree,&treeValide,&app); + } #endif -} -} + } + } - // ----------------------------------------------------- + // ----------------------------------------------------- - return 0; + return 0; } diff --git a/Tests/Utils/testFmmAlgorithmTsm.cpp b/Tests/Utils/testFmmAlgorithmTsm.cpp index 5dd9f0259359a97d04be96668690ea5f0c3a70cc..561881a8b4b21ceb5d7dcc2efbaabf524f76972f 100755 --- a/Tests/Utils/testFmmAlgorithmTsm.cpp +++ b/Tests/Utils/testFmmAlgorithmTsm.cpp @@ -43,6 +43,8 @@ #include "../../Src/Components/FTestParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that each particles is impacted each other particles @@ -52,6 +54,11 @@ class FTestCellTsm: public FTestCell , public FExtendCellType{ // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Test FMM TSM (target source model) algorithm by counting the nb of interactions each particle receive.", + FParameterDefinitions::OctreeHeight, FParameterDefinitions::OctreeSubHeight, + FParameterDefinitions::NbParticles); + typedef FTestCellTsm CellClassTyped; typedef FTestParticleContainer ContainerClassTyped; @@ -64,9 +71,9 @@ 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,"-h", 5); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); - const int NbPart = FParameters::getValue(argc,argv,"-nb", 2000000); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); + const int NbPart = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 2000000); FTic counter; ////////////////////////////////////////////////////////////////////////////////// diff --git a/Tests/Utils/testFmmDemonstration.cpp b/Tests/Utils/testFmmDemonstration.cpp index c34ea474ceaffdc8868e9d3474d935b0991de1f1..f01ef913f2c494abbdfad33f61b0ed6d516259b4 100755 --- a/Tests/Utils/testFmmDemonstration.cpp +++ b/Tests/Utils/testFmmDemonstration.cpp @@ -42,6 +42,8 @@ #include "../../Src/Files/FRandomLoader.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + // My cell is actually a basic cell => minimum of data class MyCell : public FBasicCell { }; @@ -131,6 +133,11 @@ public: int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Explains how to use ScalFMM (only the code is interesting).", + FParameterDefinitions::OctreeHeight, FParameterDefinitions::OctreeSubHeight, + FParameterDefinitions::NbParticles); + // Custom data structure here typedef MyCell CellClass; typedef MyContainer ContainerClass; @@ -149,9 +156,9 @@ int main(int argc, char ** argv){ ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// - const int NbLevels = FParameters::getValue(argc,argv,"-h", 5); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); - const int NbPart = FParameters::getValue(argc,argv,"-pn", 20); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); + const int NbPart = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 20); FTic counter; ////////////////////////////////////////////////////////////////////////////////// diff --git a/Tests/Utils/testLapack.cpp b/Tests/Utils/testLapack.cpp index ecf3f327e5ebf0b835a23933767fb6d2eb8f1f63..e3756d10907e14b9fffdf3374204ec0dc0ed7b72 100644 --- a/Tests/Utils/testLapack.cpp +++ b/Tests/Utils/testLapack.cpp @@ -24,98 +24,100 @@ #include "../../Src/Utils/FBlas.hpp" #include "../../Src/Utils/FTic.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** * Test functionality of C - interfaced LAPACK functions */ -int main() +int main(int argc, char ** argv) { - FTic time; + FHelpDescribeAndExit(argc, argv, "Test the lapack compilation and linking (only the code is interesting)."); - /* + /* * List of tested functions: * Cholesky decomposition: FBlas::potrf() * TODO SVD: FBlas::gesvd() * TODO QR decomposition: FBlas::geqrf() */ - const unsigned int m = 4, n = 4; - FReal* A = new FReal [m * n]; // matrix: column major ordering - - // A= LL^T //////////////////////////////////// - // define symmetric definite positive matrix A - A[0]=5; A[10]=4; A[15]=7; - A[1]=A[3]=A[4]=A[12]=2; - A[6]=A[7]=A[9]=A[13]=1; - A[2]=A[5]=A[8]=3; - A[11]=A[14]=-1; - - // copy A in C - FReal* C = new FReal [m * n]; // matrix: column major ordering - for (unsigned int ii=0; ii<m; ++ii) - for (unsigned int jj=0; jj<n; ++jj) - C[ii*m + jj]=A[ii*m + jj]; - - std::cout<<"\nA=["<<std::endl; - for (unsigned int i=0; i<m; ++i) { - for (unsigned int j=0; j<n; ++j) - std::cout << A[i*n+j] << " "; - std::cout<< std::endl; - } - std::cout<<"]"<<std::endl; - - // perform Cholesky decomposition - std::cout<<"\nCholesky decomposition "; - int INF = FBlas::potrf(m, A, n); - if(INF==0) {std::cout<<"succeeded!"<<std::endl;} - else {std::cout<<"failed!"<<std::endl;} - - std::cout<<"\nA_out=["<<std::endl; - for (unsigned int i=0; i<m; ++i) { - for (unsigned int j=0; j<n; ++j) - std::cout << A[i*n+j] << " "; - std::cout<<std::endl; - } - std::cout<<"]"<<std::endl; - - // build lower matrix - FReal* L = new FReal [m * n]; // matrix: column major ordering - for (unsigned int ii=0; ii<m; ++ii) - for (unsigned int jj=0; jj<n; ++jj){ - if(ii<=jj) - L[ii*m + jj]=A[ii*m + jj]; - else - L[ii*m + jj]=0.; + const unsigned int m = 4, n = 4; + FReal* A = new FReal [m * n]; // matrix: column major ordering + + // A= LL^T //////////////////////////////////// + // define symmetric definite positive matrix A + A[0]=5; A[10]=4; A[15]=7; + A[1]=A[3]=A[4]=A[12]=2; + A[6]=A[7]=A[9]=A[13]=1; + A[2]=A[5]=A[8]=3; + A[11]=A[14]=-1; + + // copy A in C + FReal* C = new FReal [m * n]; // matrix: column major ordering + for (unsigned int ii=0; ii<m; ++ii) + for (unsigned int jj=0; jj<n; ++jj) + C[ii*m + jj]=A[ii*m + jj]; + + std::cout<<"\nA=["<<std::endl; + for (unsigned int i=0; i<m; ++i) { + for (unsigned int j=0; j<n; ++j) + std::cout << A[i*n+j] << " "; + std::cout<< std::endl; } - - std::cout<<"\nL=["<<std::endl; - for (unsigned int i=0; i<m; ++i) { - for (unsigned int j=0; j<n; ++j) - std::cout << L[i*n+j] << " "; - std::cout<< std::endl; - } - std::cout<<"]"<<std::endl; - - // verify result by computing B=LL^T - FReal* B = new FReal [m * n]; // matrix: column major ordering - for (unsigned int ii=0; ii<m; ++ii) - for (unsigned int jj=0; jj<n; ++jj){ - B[ii*m + jj]=0.; - for (unsigned int j=0; j<n; ++j) - B[ii*m + jj]+=L[j*m + ii]*L[j*m + jj]; + std::cout<<"]"<<std::endl; + + // perform Cholesky decomposition + std::cout<<"\nCholesky decomposition "; + int INF = FBlas::potrf(m, A, n); + if(INF==0) {std::cout<<"succeeded!"<<std::endl;} + else {std::cout<<"failed!"<<std::endl;} + + std::cout<<"\nA_out=["<<std::endl; + for (unsigned int i=0; i<m; ++i) { + for (unsigned int j=0; j<n; ++j) + std::cout << A[i*n+j] << " "; + std::cout<<std::endl; } + std::cout<<"]"<<std::endl; + + // build lower matrix + FReal* L = new FReal [m * n]; // matrix: column major ordering + for (unsigned int ii=0; ii<m; ++ii) + for (unsigned int jj=0; jj<n; ++jj){ + if(ii<=jj) + L[ii*m + jj]=A[ii*m + jj]; + else + L[ii*m + jj]=0.; + } + + std::cout<<"\nL=["<<std::endl; + for (unsigned int i=0; i<m; ++i) { + for (unsigned int j=0; j<n; ++j) + std::cout << L[i*n+j] << " "; + std::cout<< std::endl; + } + std::cout<<"]"<<std::endl; + + // verify result by computing B=LL^T + FReal* B = new FReal [m * n]; // matrix: column major ordering + for (unsigned int ii=0; ii<m; ++ii) + for (unsigned int jj=0; jj<n; ++jj){ + B[ii*m + jj]=0.; + for (unsigned int j=0; j<n; ++j) + B[ii*m + jj]+=L[j*m + ii]*L[j*m + jj]; + } + + std::cout<<"\nA-LL^T=["<<std::endl; + for (unsigned int i=0; i<m; ++i) { + for (unsigned int j=0; j<n; ++j) + std::cout << B[i*n+j]-C[i*n+j] << " "; + std::cout<< std::endl; + } + std::cout<<"]"<<std::endl; - std::cout<<"\nA-LL^T=["<<std::endl; - for (unsigned int i=0; i<m; ++i) { - for (unsigned int j=0; j<n; ++j) - std::cout << B[i*n+j]-C[i*n+j] << " "; - std::cout<< std::endl; - } - std::cout<<"]"<<std::endl; - - delete [] A; - delete [] B; - delete [] C; + delete [] A; + delete [] B; + delete [] C; - return 0; + return 0; } diff --git a/Tests/Utils/testLoader.cpp b/Tests/Utils/testLoader.cpp index 97a364ebf904787cbdb29540ada84fc4d942c8b4..e64dde6cdc85f1c932c4103811476fd0ba6f9b67 100755 --- a/Tests/Utils/testLoader.cpp +++ b/Tests/Utils/testLoader.cpp @@ -37,6 +37,8 @@ #include "../../Src/Components/FBasicParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** * In this file we show an example of FBasicLoader use * Inserting 2000000 particles ... @@ -46,6 +48,9 @@ */ int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, "Load a file and put the particles in a tree", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight); + typedef FBasicParticleContainer<0> ContainerClass; typedef FSimpleLeaf< ContainerClass > LeafClass; typedef FOctree< FBasicCell, ContainerClass , LeafClass > OctreeClass; @@ -58,7 +63,7 @@ int main(int argc, char ** argv){ // Use testLoaderCreate.exe to create this file FTic counter; - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.basic"); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.basic"); std::cout << "Opening : " << filename << "\n"; // open basic particles loader @@ -70,7 +75,7 @@ int main(int argc, char ** argv){ { // otree - OctreeClass tree(FParameters::getValue(argc,argv,"-h", 5), FParameters::getValue(argc,argv,"-sh", 3), + OctreeClass tree(FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5), FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3), loader.getBoxWidth(), loader.getCenterOfBox()); // ----------------------------------------------------- diff --git a/Tests/Utils/testLoaderFMATsm.cpp b/Tests/Utils/testLoaderFMATsm.cpp index d2e4860123fdfa6c545aab85bf32834cb2880d02..42f18ce602070f9b3bac7c3a455ba07defee4db6 100755 --- a/Tests/Utils/testLoaderFMATsm.cpp +++ b/Tests/Utils/testLoaderFMATsm.cpp @@ -38,9 +38,13 @@ #include "../../Src/Utils/FParameters.hpp" +#include "../../Src/Utils/FParameterNames.hpp" int main(int argc, char ** argv ){ + FHelpDescribeAndExit(argc, argv, "Load a file and put the particles in a tree with the TSM (target source model)", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight); + typedef FBasicParticleContainer<1> ContainerClass; typedef FTypedLeaf< ContainerClass > LeafClass; typedef FOctree< FBasicCell, ContainerClass , LeafClass > OctreeClass; @@ -52,7 +56,7 @@ int main(int argc, char ** argv ){ // Use testLoaderCreate.exe to create this file FTic counter; - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.tsm.fma"); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.tsm.fma"); std::cout << "Opening : " << filename << "\n"; // open basic particles loader @@ -63,7 +67,7 @@ int main(int argc, char ** argv ){ } { // otree - OctreeClass tree(FParameters::getValue(argc,argv,"-h", 5), FParameters::getValue(argc,argv,"-sh", 3), + OctreeClass tree(FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5), FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3), loader.getBoxWidth(),loader.getCenterOfBox()); // ----------------------------------------------------- diff --git a/Tests/Utils/testLoaderFMATsmCreate.cpp b/Tests/Utils/testLoaderFMATsmCreate.cpp index 29538e00c40ed9c46649a384125ee251f989fd52..84590d1a996a58a471ac3cfd07a8810c95ad0551 100755 --- a/Tests/Utils/testLoaderFMATsmCreate.cpp +++ b/Tests/Utils/testLoaderFMATsmCreate.cpp @@ -24,9 +24,15 @@ #include "../../Src/Utils/FGlobal.hpp" #include "../../Src/Utils/FParameters.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + // This file can generate basic particles files in the FMA format int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, "Create a file for the TSM (target source model)", + FParameterDefinitions::NbParticles, FParameterDefinitions::OutputFile, + FParameterDefinitions::PhysicalValue); + ///////////////////////What we do///////////////////////////// std::cout << ">> This executable can create a FMA-like particles files (this is not a fma file!)"; std::cout << ">> You can pass a filename in parameter else the program will use\n"; @@ -37,8 +43,8 @@ int main(int argc, char ** argv){ std::cout << ">> [x] [y] [z] [physical value] [1 if target 0 if source]...\n"; ////////////////////////////////////////////////////////////// // Nb of particles - const long NbParticles = FParameters::getValue(argc,argv,"-nb", long(20000)); - const FReal physicalValue = FParameters::getValue(argc,argv,"-pv", FReal(0.1)); + const long NbParticles = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, long(20000)); + const FReal physicalValue = FParameters::getValue(argc,argv,FParameterDefinitions::PhysicalValue.options, FReal(0.1)); // Center of the box const FReal XCenter = 0.5; @@ -48,7 +54,7 @@ int main(int argc, char ** argv){ // Box width const FReal BoxWidth = 1.0/2; // Output file please let .temp extension - const char* const Output = FParameters::getStr(argc,argv,"-f", "../Data/test20k.tsm.fma"); + const char* const Output = FParameters::getStr(argc,argv,FParameterDefinitions::OutputFile.options, "../Data/test20k.tsm.fma"); std::cout << "Creating : " << Output << "\n"; // Create file diff --git a/Tests/Utils/testMemStats.cpp b/Tests/Utils/testMemStats.cpp index a777b190f31af639f1857e48ac2957f064f378a5..97e664ba5416e6f5f9ab6894ed8f82bba26e347c 100755 --- a/Tests/Utils/testMemStats.cpp +++ b/Tests/Utils/testMemStats.cpp @@ -40,6 +40,8 @@ #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that each particles is impacted each other particles @@ -48,6 +50,10 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ { + FHelpDescribeAndExit(argc, argv, "Show the memory usage (if mem stats is turned on at the compilation)", + FParameterDefinitions::OctreeHeight, FParameterDefinitions::OctreeSubHeight, + FParameterDefinitions::NbParticles, FParameterDefinitions::SHDevelopment); + typedef FSphericalCell CellClass; typedef FP2PParticleContainer<> ContainerClass; @@ -62,10 +68,10 @@ 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,"-h", 5); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); - const int NbPart = FParameters::getValue(argc,argv,"-nb", 2000000); - const int DevP = FParameters::getValue(argc,argv,"-p", 5); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); + const int NbPart = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 2000000); + const int DevP = FParameters::getValue(argc,argv,FParameterDefinitions::SHDevelopment.options, 5); const FPoint centerOfBox = FPoint(0.5,0.5,0.5); FTic counter; diff --git a/Tests/Utils/testMpiCsvSaver.cpp b/Tests/Utils/testMpiCsvSaver.cpp index fdab77ae018e5b43c8e375463f6e3c830d4363c9..e9d20790a4fbfe07369489dba4c2ffc69394bc46 100755 --- a/Tests/Utils/testMpiCsvSaver.cpp +++ b/Tests/Utils/testMpiCsvSaver.cpp @@ -37,9 +37,11 @@ #include "../../Src/Components/FBasicCell.hpp" #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + class VelocityContainer : public FP2PParticleContainer<> { - typedef FP2PParticleContainer<> Parent; + typedef FP2PParticleContainer<> Parent; FVector<FPoint> velocities; @@ -85,9 +87,9 @@ struct TestParticle{ FPoint position; FReal physicalValue; FReal potential; - FReal forces[3]; - FPoint velocity; - const FPoint& getPosition(){ + FReal forces[3]; + FPoint velocity; + const FPoint& getPosition(){ return position; } }; @@ -128,6 +130,12 @@ public: // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Convert the data from a file into a csv file to load into Paraview for example.\n" + "It puts the file into the /tmp dir and the code is an example of using FTreeMpiCsvSaver.", + FParameterDefinitions::OctreeHeight, FParameterDefinitions::OctreeSubHeight, + FParameterDefinitions::InputFile); + typedef FBasicCell CellClass; typedef VelocityContainer ContainerClass; @@ -138,10 +146,10 @@ int main(int argc, char ** argv){ ////////////////////////////////////////////////////////////// FMpi app( argc, argv); - const int NbLevels = FParameters::getValue(argc,argv,"-depth", 6); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-subdepth", 3); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 6); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); - GalaxyLoader loader(FParameters::getStr(argc,argv,"-f", "../Data/galaxy.fma")); + GalaxyLoader loader(FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/galaxy.fma")); // ----------------------------------------------------- @@ -165,14 +173,14 @@ int main(int argc, char ** argv){ // ----------------------------------------------------- { - FTreeMpiCsvSaver<OctreeClass, ContainerClass> saver("./out/test%d.csv", app.global() , false); + FTreeMpiCsvSaver<OctreeClass, ContainerClass> saver("/tmp/test%d.csv", app.global() , false); saver.exportTree(&tree); } // ----------------------------------------------------- { - FTreeMpiCsvSaver<OctreeClass, ContainerClass> saver("./out/htest%d.csv", app.global() , true); + FTreeMpiCsvSaver<OctreeClass, ContainerClass> saver("/tmp/htest%d.csv", app.global() , true); saver.exportTree(&tree); } diff --git a/Tests/Utils/testOctree.cpp b/Tests/Utils/testOctree.cpp index 95df3c5293e4184ee74327641200f1590b6025b9..afb36879701275cf038424eabdc405287e9215d7 100755 --- a/Tests/Utils/testOctree.cpp +++ b/Tests/Utils/testOctree.cpp @@ -35,11 +35,17 @@ #include "../../Src/Files/FRandomLoader.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** * In this file we show how to use octree */ int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Show how to use an octree (only the code is interesting)", + FParameterDefinitions::NbParticles); + typedef FBasicParticleContainer<0> ContainerClass; typedef FSimpleLeaf< ContainerClass > LeafClass; typedef FOctree< FBasicCell, ContainerClass , LeafClass > OctreeClass; @@ -48,7 +54,7 @@ int main(int argc, char ** argv){ std::cout << ">> It is only interesting to wath the code to understand\n"; std::cout << ">> how to use the Octree\n"; ////////////////////////////////////////////////////////////// - const int NbPart = FParameters::getValue(argc,argv,"-nb", 2000000); + const int NbPart = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 2000000); FTic counter; FRandomLoader loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1); diff --git a/Tests/Utils/testOctreeFuncteur.cpp b/Tests/Utils/testOctreeFuncteur.cpp index a8851dd7ef6ed5774477057407998b804807fb37..cc8a7a17305da66c64c71d30ef02989e45a5b67e 100644 --- a/Tests/Utils/testOctreeFuncteur.cpp +++ b/Tests/Utils/testOctreeFuncteur.cpp @@ -35,11 +35,17 @@ #include "../../Src/Files/FRandomLoader.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** * In this file we show how to use octree's functeur */ int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Show how to use an octree functeur (only the code is interesting)", + FParameterDefinitions::NbParticles); + typedef FBasicCell CellClass; typedef FBasicParticleContainer<0> ContainerClass; typedef FSimpleLeaf< ContainerClass > LeafClass; @@ -49,7 +55,7 @@ int main(int argc, char ** argv){ std::cout << ">> It is only interesting to wath the code to understand\n"; std::cout << ">> how to use the Octree\n"; ////////////////////////////////////////////////////////////// - const int NbPart = FParameters::getValue(argc,argv,"-nb", 2000); + const int NbPart = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 2000); FTic counter; FRandomLoader loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1); diff --git a/Tests/Utils/testOctreeIter.cpp b/Tests/Utils/testOctreeIter.cpp index db7f2c61bc1978ac5a653e34b361462b6f4f633f..506fdac89944abe40f39a158108f83d4ab429322 100755 --- a/Tests/Utils/testOctreeIter.cpp +++ b/Tests/Utils/testOctreeIter.cpp @@ -35,12 +35,19 @@ #include "../../Src/Utils/FTic.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** * In this file we show how to use octree with iteration * This is a good example to understand FOctree::Iterator. */ int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Show how to iterate on an octree (only the code is interesting)", + FParameterDefinitions::NbParticles, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight); + typedef FBasicParticleContainer<0> ContainerClass; typedef FSimpleLeaf< ContainerClass > LeafClass; typedef FOctree< FBasicCell, ContainerClass , LeafClass > OctreeClass; @@ -50,9 +57,9 @@ int main(int argc, char ** argv){ std::cout << ">> how to use octree iterator.\n"; ////////////////////////////////////////////////////////////// - const int NbLevels = FParameters::getValue(argc,argv,"-h", 9); - const int NbSubLevels = FParameters::getValue(argc,argv,"-sh", 3); - const int NbPart = FParameters::getValue(argc,argv,"-nb", 2000000); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 9); + const int NbSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); + const int NbPart = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 2000000); FTic counterTime; diff --git a/Tests/Utils/testOctreePrintMorton.cpp b/Tests/Utils/testOctreePrintMorton.cpp index 77f45334daedb37b145fa545fc58feb1db1fc3ff..c6454ec31ad51b5580107a9379ba89b0ad9d2781 100755 --- a/Tests/Utils/testOctreePrintMorton.cpp +++ b/Tests/Utils/testOctreePrintMorton.cpp @@ -25,6 +25,7 @@ #include "../../Src/Containers/FTreeCoordinate.hpp" #include "../../Src/Utils/FPoint.hpp" #include "../../Src/Utils/FMath.hpp" +#include "../../Src/Utils/FParameterNames.hpp" /** * In this file we show the morton indexed for each boxes @@ -52,7 +53,10 @@ std::string MortonToBinary(MortonIndex index, int level){ } -int main(int , char ** ){ +int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Print the morton and cell properties of an octree\n" + "it is also interesting to look at the code if one needs to work with morton indexes"); ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test morton index.\n"; ////////////////////////////////////////////////////////////// diff --git a/Tests/Utils/testOctreeRearrange.cpp b/Tests/Utils/testOctreeRearrange.cpp index 3bf9dbcadc888a3897b79ffdd10a9ec300b84cb9..6536376e77d2572d623b8c4398d0da11b836d82a 100755 --- a/Tests/Utils/testOctreeRearrange.cpp +++ b/Tests/Utils/testOctreeRearrange.cpp @@ -34,6 +34,8 @@ #include "../../Src/Arranger/FOctreeArranger.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + struct TestParticle{ FPoint position; const FPoint& getPosition(){ @@ -62,6 +64,12 @@ public: // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Put the particles into a tree, then change the position of some particles and update the tree.\n" + "This method should be used to avoid the tree reconstruction.", + FParameterDefinitions::NbParticles, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight); + typedef FBasicCell CellClass; typedef FBasicParticleContainer<0> ContainerClass; @@ -72,9 +80,9 @@ 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,"-h", 7); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); - const int NbPart = FParameters::getValue(argc,argv,"-nb", 2000000); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 7); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); + const int NbPart = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 2000000); FTic counter; diff --git a/Tests/Utils/testOctreeRearrangeProc.cpp b/Tests/Utils/testOctreeRearrangeProc.cpp index e6e4c094758767bfd89242fd3d3fc2818897d319..4c32612981b53851710035ab0fe790050b8e1c47 100755 --- a/Tests/Utils/testOctreeRearrangeProc.cpp +++ b/Tests/Utils/testOctreeRearrangeProc.cpp @@ -42,6 +42,8 @@ #include "../../Src/BalanceTree/FLeafBalance.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + struct TestParticle{ FPoint position; const FPoint& getPosition(){ @@ -72,6 +74,13 @@ public: // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "In distributed!\n" + "Put the particles into a tree, then change the position of some particles and update the tree.\n" + "This method should be used to avoid the tree reconstruction.", + FParameterDefinitions::NbParticles, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight); + typedef FTestCell CellClass; typedef FBasicParticleContainer<0> ContainerClass; @@ -84,9 +93,9 @@ int main(int argc, char ** argv){ FMpi app(argc, argv); - const int NbLevels = FParameters::getValue(argc,argv,"-h", 7); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); - const int NbPart = FParameters::getValue(argc,argv,"-nb", 20000); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 7); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); + const int NbPart = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 20000); FTic counter; diff --git a/Tests/Utils/testStatsTree.cpp b/Tests/Utils/testStatsTree.cpp index 43add2bd5ccb7925f5a71e8b65d55d41bb66166a..e0bd4ad00481c7c2e3237031e5ddaa4c2b724d7a 100755 --- a/Tests/Utils/testStatsTree.cpp +++ b/Tests/Utils/testStatsTree.cpp @@ -39,6 +39,8 @@ #include "../../Src/Components/FBasicParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** This program show an example of use of * the fmm basic algo @@ -49,6 +51,11 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Print a lot of information about the tree build from a given file.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight); + typedef FBasicParticleContainer<0> ContainerClass; typedef FSimpleLeaf< ContainerClass > LeafClass; typedef FOctree< FBasicCell, ContainerClass , LeafClass > OctreeClass; @@ -56,11 +63,11 @@ int main(int argc, char ** argv){ std::cout << ">> This executable has to be used to show some stat about the tree.\n"; ////////////////////////////////////////////////////////////// - const int NbLevels = FParameters::getValue(argc,argv,"-h", 5); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); FTic counter; - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; FFmaGenericLoader loader(filename); diff --git a/Tests/Utils/testTemplateExample.cpp b/Tests/Utils/testTemplateExample.cpp index bd838b26c7df1e41a4d7cf4f83f631515e5ef46d..27834ea6d4691b4232cc9ac4e241f7af6f9bbe35 100644 --- a/Tests/Utils/testTemplateExample.cpp +++ b/Tests/Utils/testTemplateExample.cpp @@ -21,6 +21,8 @@ #include "../../Src/Utils/FTemplate.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + #include <iostream> struct RunContainer{ @@ -42,7 +44,10 @@ struct RunContainer{ // Compile with g++ -std=c++11 main.cpp -o test.exe -int main(){ +int main(int argc, char** argv){ + FHelpDescribeAndExit(argc, argv, + "Only the code is interesting in order to understand the multi-template compilation."); + // This will call the For method (maybe several times) FForAll::For<int, 0, 20, 1, RunContainer>(45.4, 55); diff --git a/Tests/Utils/testTic.cpp b/Tests/Utils/testTic.cpp index 2f0c36b8097dca39a1226cc856b1b9fefbaab094..897c42b354b47f60d462fc3fe99d670215c84dae 100755 --- a/Tests/Utils/testTic.cpp +++ b/Tests/Utils/testTic.cpp @@ -15,6 +15,7 @@ // =================================================================================== #include <iostream> #include "../../Src/Utils/FTic.hpp" +#include "../../Src/Utils/FParameterNames.hpp" #include <cstdlib> #include <unistd.h> @@ -23,7 +24,9 @@ * Here we show an example of using FTic */ -int main(){ +int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Only the code is interesting in order to understand the use of timers."); ///////////////////////What we do///////////////////////////// std::cout << ">> This executable is useless to execute.\n"; std::cout << ">> It is only interesting to wath the code to understand\n"; diff --git a/Tests/Utils/testTreeIO.cpp b/Tests/Utils/testTreeIO.cpp index 5bb201d7d36529449c84b7d57fc27719dff5ed07..62e536c813f26778e1712325736fb57bc9da11a7 100755 --- a/Tests/Utils/testTreeIO.cpp +++ b/Tests/Utils/testTreeIO.cpp @@ -32,6 +32,7 @@ #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" #include "../../Src/Components/FSimpleLeaf.hpp" +#include "../../Src/Utils/FParameterNames.hpp" #include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" @@ -46,11 +47,11 @@ void usage() { } // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Load and store a tree (only the code is interesting).", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::OutputFile); - if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")){ - usage() ; - exit(EXIT_SUCCESS); - } typedef FSphericalCell CellClass; typedef FP2PParticleContainer<> ContainerClass; @@ -60,12 +61,12 @@ int main(int argc, char ** argv){ ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to load or retrieve an entier tree.\n"; ////////////////////////////////////////////////////////////// - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); + const unsigned int TreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeHeight.options, 5); + const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, FParameterDefinitions::OctreeSubHeight.options, 2); FTic counter; - const std::string filenameIN = FParameters::getStr(argc,argv,"-fin", "../Data/test20k.fma"); - const std::string filenameOUT = FParameters::getStr(argc,argv,"-fout", "tmp_tree.data"); + const std::string filenameIN = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); + const std::string filenameOUT = FParameters::getStr(argc,argv,FParameterDefinitions::OutputFile.options, "tmp_tree.data"); std::cout << "Opening : " << filenameIN << "\n"; FFmaGenericLoader loader(filenameIN); diff --git a/Tests/Utils/testUnifInterpolator.cpp b/Tests/Utils/testUnifInterpolator.cpp index 5d93e3ab49c7c5337f6cd813d1bac17912fc10e7..f51c881346f560b950d588fc5f00ff3a13834aec 100755 --- a/Tests/Utils/testUnifInterpolator.cpp +++ b/Tests/Utils/testUnifInterpolator.cpp @@ -34,6 +34,7 @@ #include "Utils/FAssert.hpp" #include "Utils/FPoint.hpp" +#include "../../Src/Utils/FParameterNames.hpp" #include "Kernels/Uniform/FUnifInterpolator.hpp" #include "Kernels/Interpolation/FInterpMatrixKernel.hpp" @@ -54,498 +55,500 @@ * In this file we show how to use octree */ -int main(int, char **){ - typedef FP2PParticleContainer<> ContainerClass; - typedef FSimpleLeaf<ContainerClass> LeafClass; - typedef FInterpMatrixKernelR MatrixKernelClass; - - - ///////////////////////What we do///////////////////////////// - std::cout << "\nTask: Compute interactions between source particles in leaf Y and target\n"; - std::cout << " particles in leaf X. Compare the fast summation K ~ Lx K Ly' with the\n"; - std::cout << " direct computation.\n" << std::endl; - ////////////////////////////////////////////////////////////// - - MatrixKernelClass MatrixKernel; - const FReal FRandMax = FReal(RAND_MAX); - FTic time; - - - // Leaf size - FReal width = FReal(3.723); - - //////////////////////////////////////////////////////////////////// - LeafClass X; - FPoint cx(0., 0., 0.); - const unsigned long M = 20000; - std::cout << "Fill the leaf X of width " << width - << " centered at cx=" << cx << " with M=" << M << " target particles" << std::endl; - { - for(unsigned long i=0; i<M; ++i){ - FReal x = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getX(); - FReal y = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getY(); - FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getZ(); - X.push(FPoint(x, y, z), FReal(rand())/FRandMax); +int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, "Test the uniform interpolator (only the code is interesting)"); + + typedef FP2PParticleContainer<> ContainerClass; + typedef FSimpleLeaf<ContainerClass> LeafClass; + typedef FInterpMatrixKernelR MatrixKernelClass; + + + ///////////////////////What we do///////////////////////////// + std::cout << "\nTask: Compute interactions between source particles in leaf Y and target\n"; + std::cout << " particles in leaf X. Compare the fast summation K ~ Lx K Ly' with the\n"; + std::cout << " direct computation.\n" << std::endl; + ////////////////////////////////////////////////////////////// + + MatrixKernelClass MatrixKernel; + const FReal FRandMax = FReal(RAND_MAX); + FTic time; + + + // Leaf size + FReal width = FReal(3.723); + + //////////////////////////////////////////////////////////////////// + LeafClass X; + FPoint cx(0., 0., 0.); + const unsigned long M = 20000; + std::cout << "Fill the leaf X of width " << width + << " centered at cx=" << cx << " with M=" << M << " target particles" << std::endl; + { + for(unsigned long i=0; i<M; ++i){ + FReal x = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getX(); + FReal y = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getY(); + FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getZ(); + X.push(FPoint(x, y, z), FReal(rand())/FRandMax); + } } - } - - - //////////////////////////////////////////////////////////////////// - LeafClass Y; - // FPoint cy(FReal(2.)*width, 0., 0.); - FPoint cy(FReal(2.)*width, FReal(2.)*width, 0.); - - const unsigned long N = 20000; - std::cout << "Fill the leaf Y of width " << width - << " centered at cy=" << cy << " with N=" << N << " target particles" << std::endl; - { - for(unsigned long i=0; i<N; ++i){ - FReal x = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getX(); - FReal y = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getY(); - FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getZ(); - Y.push(FPoint(x, y, z), FReal(rand())/FRandMax); + + + //////////////////////////////////////////////////////////////////// + LeafClass Y; + // FPoint cy(FReal(2.)*width, 0., 0.); + FPoint cy(FReal(2.)*width, FReal(2.)*width, 0.); + + const unsigned long N = 20000; + std::cout << "Fill the leaf Y of width " << width + << " centered at cy=" << cy << " with N=" << N << " target particles" << std::endl; + { + for(unsigned long i=0; i<N; ++i){ + FReal x = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getX(); + FReal y = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getY(); + FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getZ(); + Y.push(FPoint(x, y, z), FReal(rand())/FRandMax); + } } - } - //////////////////////////////////////////////////////////////////// - // approximative computation - const unsigned int ORDER = 4; - const unsigned int nnodes = TensorTraits<ORDER>::nnodes; - typedef FUnifInterpolator<ORDER,MatrixKernelClass> InterpolatorClass; - InterpolatorClass S; + //////////////////////////////////////////////////////////////////// + // approximative computation + const unsigned int ORDER = 4; + const unsigned int nnodes = TensorTraits<ORDER>::nnodes; + typedef FUnifInterpolator<ORDER,MatrixKernelClass> InterpolatorClass; + InterpolatorClass S; - std::cout << "\nCompute interactions approximatively, interpolation order = " << ORDER << " ..." << std::endl; + std::cout << "\nCompute interactions approximatively, interpolation order = " << ORDER << " ..." << std::endl; - std::cout << "\nP2M ... " << std::flush; - time.tic(); - // Anterpolate: W_n = \sum_j^N S(y_j,\bar y_n) * w_j - FReal W[nnodes]; // multipole expansion - S.applyP2M(cy, width, W, Y.getSrc()); // the multipole expansions are set to 0 in S.applyP2M - std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; + std::cout << "\nP2M ... " << std::flush; + time.tic(); + // Anterpolate: W_n = \sum_j^N S(y_j,\bar y_n) * w_j + FReal W[nnodes]; // multipole expansion + S.applyP2M(cy, width, W, Y.getSrc()); // the multipole expansions are set to 0 in S.applyP2M + std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; - std::cout << "M2L ... " << std::flush; - time.tic(); - // Multipole to local: F_m = \sum_n^L K(\bar x_m, \bar y_n) * W_n - FPoint rootsX[nnodes], rootsY[nnodes]; - FUnifTensor<ORDER>::setRoots(cx, width, rootsX); - FUnifTensor<ORDER>::setRoots(cy, width, rootsY); + std::cout << "M2L ... " << std::flush; + time.tic(); + // Multipole to local: F_m = \sum_n^L K(\bar x_m, \bar y_n) * W_n + FPoint rootsX[nnodes], rootsY[nnodes]; + FUnifTensor<ORDER>::setRoots(cx, width, rootsX); + FUnifTensor<ORDER>::setRoots(cy, width, rootsY); - FReal F[nnodes]; // local expansion - for (unsigned int i=0; i<nnodes; ++i) { - F[i] = FReal(0.); - for (unsigned int j=0; j<nnodes; ++j){ + FReal F[nnodes]; // local expansion + for (unsigned int i=0; i<nnodes; ++i) { + F[i] = FReal(0.); + for (unsigned int j=0; j<nnodes; ++j){ - F[i] += MatrixKernel.evaluate(rootsX[i], rootsY[j]) * W[j]; + F[i] += MatrixKernel.evaluate(rootsX[i], rootsY[j]) * W[j]; + } } - } - std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; + std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; - //////////////////////////////////////////////////////////////////////////// - // Store M2L in K and apply K - FReal K[nnodes*nnodes]; // local expansion - for (unsigned int i=0; i<nnodes; ++i) { - for (unsigned int j=0; j<nnodes; ++j){ - K[i*nnodes+j] = MatrixKernel.evaluate(rootsX[i], rootsY[j]); + //////////////////////////////////////////////////////////////////////////// + // Store M2L in K and apply K + FReal K[nnodes*nnodes]; // local expansion + for (unsigned int i=0; i<nnodes; ++i) { + for (unsigned int j=0; j<nnodes; ++j){ + K[i*nnodes+j] = MatrixKernel.evaluate(rootsX[i], rootsY[j]); + } + } + std::cout<< "Apply M2L in usual sense: "; + time.tic(); + + for (unsigned int i=0; i<nnodes; ++i) { + F[i] = FReal(0.); + for (unsigned int j=0; j<nnodes; ++j){ + + F[i] += K[i*nnodes+j] * W[j]; + + } + } + + time.tac(); + std::cout << "took " << time.elapsed() << "sec." << std::endl; + + // PB: Verify storage improvement works (indexing etc...) + // 1) store circulant matrix + const unsigned int rc = (2*ORDER-1)*(2*ORDER-1)*(2*ORDER-1); + FReal C[rc]; + + typedef FUnifTensor<ORDER> TensorType; + unsigned int node_diff[nnodes*nnodes]; + TensorType::setNodeIdsDiff(node_diff); + unsigned int node_ids[nnodes][3]; + TensorType::setNodeIds(node_ids); + unsigned int node_ids_pairs[rc][2]; + TensorType::setNodeIdsPairs(node_ids_pairs); + + // std::cout << "2*order-1=" << 2*ORDER-1 << std::endl; + unsigned int ido=0; + for(unsigned int l=0; l<2*ORDER-1; ++l) + for(unsigned int m=0; m<2*ORDER-1; ++m) + for(unsigned int n=0; n<2*ORDER-1; ++n){ + + C[ido] + = MatrixKernel.evaluate(rootsX[node_ids_pairs[ido][0]], + rootsY[node_ids_pairs[ido][1]]); + ido++; + } + + // // Display C (gathers every values of K that need to be stored, + // // corresponds to the first line of the padded matrix (reverse order?)) + // std::cout<<"C="<<std::endl; + // for (unsigned int n=0; n<rankpad; ++n) + // std::cout<< C[ido] << ", "; + // std::cout<<std::endl; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // K is a block Toeplitz matrix + // i.e. a blockwise Toeplitz matrix where the block also have the Toeplitz structure. + // e.g. for ORDER=3: K=[K_{1,1} K_{1,2} K_{1,3}, where K_{i,j}=[k11 k12 k13, + // K_{2,1} K_{1,1} K_{1,2}, k21 k11 k12, + // K_{3,1} K_{2,1} K_{1,1}]; k31 k21 k11]; + // K is of size order^3 x order^3 + // (i.e. order^2 x order^2 Toeplitz blocks of size order x order), + // K is very close to be Toeplitz itself and even circulant. + // In order to actually embed K into a circulant matrix C one just + // needs to insert (ORDER-1) extra lines/columns (to each block). + + // std::cout<< "K=" <<std::endl; + // for (unsigned int i=0; i<nnodes; ++i){ + // for (unsigned int j=0; j<nnodes; ++j){ + // std::cout<< K[i*nnodes+j]<<", "; + // } + // std::cout<<std::endl; + // } + // std::cout<<std::endl; + + if(ORDER<4){// display some extra results for low orders + + // Check multi-index + std::cout<< "node_ids=" <<std::endl; + for (unsigned int i=0; i<nnodes; ++i) + std::cout<< node_ids[i][0] <<", " + << node_ids[i][1] <<", " + << node_ids[i][2] <<", "<<std::endl; + std::cout<<std::endl; + + // Check multi-index diff + std::cout<< "node_ids=" <<std::endl; + for (unsigned int i=0; i<nnodes; ++i){ + for (unsigned int j=0; j<nnodes; ++j) + std::cout<< "(" << int(node_ids[i][0]-node_ids[j][0]) <<"," + << int(node_ids[i][1]-node_ids[j][1]) <<"," + << int(node_ids[i][2]-node_ids[j][2]) <<"), "; + std::cout<<std::endl; + } + std::cout<<std::endl; + + // Check matrix node_diff + std::cout<< "node_diff=" <<std::endl; + for (unsigned int i=0; i<nnodes; ++i){ + for (unsigned int j=0; j<nnodes; ++j){ + std::cout<< node_diff[i*nnodes+j] <<", "; + } + std::cout<<std::endl; + } + std::cout<<std::endl; + + // // Expected ido for the (2*ORDER-1)^3x(2*ORDER-1)^3 circulant matrix + // for (unsigned int i=0; i<rc; ++i){ + // for (unsigned int j=0; j<rc; ++j){ + // if(i>j) std::cout<< i-j-1 << ", "; + // else std::cout<< rc+i-j-1 << ", "; + // } std::cout<<std::endl; + // } std::cout<<std::endl; + + // // kernel evaluated at previous ido returns a circulant matrix + // for (unsigned int i=0; i<rc/2; ++i){ + // for (unsigned int j=0; j<rc/2; ++j){ + // if(i>j) std::cout<< C[i-j-1] << ", "; + // else std::cout<< C[rc+i-j-1] << ", "; + // } std::cout<<std::endl; + // } std::cout<<std::endl; + + }// display some extra results for low orders + + // In 1D the Zero Padding consists in + // inserting ORDER-1 zeros in the multipole exp + // in order to apply the (ORDER+ORDER-1)x(ORDER+ORDER-1) + // circulant matrix to it. + // Let us extend it to the 3D case: + FReal MultExp[nnodes]; FReal PaddedMultExp[rc]; + for (unsigned int i=0; i<nnodes; ++i) MultExp[i]=W[i]; + FReal LocalExp[nnodes]; FReal PaddedLocalExp[rc]; + FBlas::setzero(nnodes,LocalExp); + FBlas::setzero(rc,PaddedLocalExp); + + // std::cout<< "Expected LocalExp: "<<std::endl; + // for (unsigned int i=0; i<nnodes; ++i) + // std::cout<< F[i] << ", "; + // std::cout<<std::endl; + + ///////////////////////////////////////////////////////////////////////////////////// + // Application of circulant Toeplitz system in PHYSICAL SPACE + std::cout<< "Apply circulant M2L in Physical space: "; + time.tic(); + for (unsigned int i=0; i<nnodes; ++i){ + + // Pad Multipole Expansion with respect to current row + FBlas::setzero(rc,PaddedMultExp); + for (unsigned int j=0; j<nnodes; ++j) + PaddedMultExp[node_diff[i*nnodes+j]]=MultExp[j]; + + // std::cout<< "Padded MultExp for row i=" << i << ": "<<std::endl; + // for (unsigned int p=0; p<rc; ++p) + // std::cout<< PaddedMultExp[p] << ", "; + // std::cout<<std::endl; + + // Application of M2L in PHYSICAL SPACE + for (unsigned int pj=0; pj<rc; ++pj) + LocalExp[i]+=C[pj]*PaddedMultExp[pj]; + + }// end i + time.tac(); + std::cout << "took " << time.elapsed() << "sec." << std::endl; + + // std::cout<< "LocalExp via product in PHYSICAL SPACE: "<<std::endl; + // for (unsigned int p=0; p<nnodes; ++p) + // std::cout<< LocalExp[p] << ", "; + // std::cout<<std::endl; + // std::cout<<std::endl; + + ///////////////////////////////////////////////////////////////////////////////////// + // Efficient application of the Toeplitz system in FOURIER SPACE + FComplex FPMultExp[rc]; + FComplex FPLocalExp[rc]; + FReal PLocalExp[rc]; + + //for (unsigned int n=0; n<rc; ++n) FPLocalExp[n]=FComplex(0.0,0.0); + FBlas::c_setzero(rc,reinterpret_cast<FReal*>(FPLocalExp)); + + FBlas::setzero(rc,PLocalExp); + + // Init DFT + const int dimfft = 1; + const int steps[dimfft] = {rc}; + //FDft Dft(rc); // direct version + FFft<dimfft> Dft; // fast version + Dft.buildDFT(steps); + + // Get first COLUMN of K and Store in T + FReal T[rc]; + // use permutations + unsigned int perm[rc]; + for(unsigned int p=0; p<rc; ++p){ + if(p>0) perm[p]=p-1; + else perm[p]=rc+p-1; + // std::cout << "perm["<< p << "]="<< perm[p] << std::endl; } - } - std::cout<< "Apply M2L in usual sense: "; - time.tic(); - for (unsigned int i=0; i<nnodes; ++i) { - F[i] = FReal(0.); + for (unsigned int i=0; i<rc; ++i){ + // keep this lines commented to see what permutation accounts for: + // for (unsigned int j=0; j<rc; ++j){ + // if(i>0) T[i]=C[i-0-1]; + // else T[i]=C[rc+i-0-1]; + T[i]=C[perm[i]]; + // } + } + + // std::cout<< "First column of C[rc x rc]: "<<std::endl; + // for (unsigned int p=0; p<rc; ++p) + // std::cout<< T[p] << ", "; + // std::cout<<std::endl; + + // Apply DFT to T + FComplex FT[rc]; + // for (unsigned int n=0; n<rc; ++n) FT[n]=FComplex(0.0,0.0); + FBlas::c_setzero(rc,reinterpret_cast<FReal*>(FT)); + + // if first COLUMN (T) of C is used + Dft.applyDFT(T,FT); + // // if first ROW of C is used + // Dft.applyDFT(C,FT); + + // Pad physical MultExp + FBlas::setzero(rc,PaddedMultExp); //part of padding for (unsigned int j=0; j<nnodes; ++j){ + // if first COLUMN (T) of C is used + PaddedMultExp[node_diff[j*nnodes]]=MultExp[j]; + // // if first ROW of C is used + // PaddedMultExp[node_diff[j]]=MultExp[j]; + } + + // std::cout<< "Padded MultExp for row i=" << i << ": "<<std::endl; + // for (unsigned int p=0; p<rc; ++p) + // std::cout<< PaddedMultExp[p] << ", "; + // std::cout<<std::endl; + - F[i] += K[i*nnodes+j] * W[j]; + // Set transformed MultExp to 0 + // for (unsigned int n=0; n<rc; ++n) FPMultExp[n]=FComplex(0.0,0.0); + FBlas::c_setzero(rc,reinterpret_cast<FReal*>(FPMultExp)); + // Transform PaddedMultExp + Dft.applyDFT(PaddedMultExp,FPMultExp); + + std::cout<< "Apply M2L in Fourier space: "; + time.tic(); + + // Application of M2L in FOURIER SPACE + // > Use FMkl::c_had for hadamard product + // if mkl is used as blas (TODO otherwise use FBlas::c_had()) + // FMkl::c_had(rc,reinterpret_cast<FReal*>(FT), + // reinterpret_cast<FReal*>(FPMultExp), + // reinterpret_cast<FReal*>(FPLocalExp)); + // > or perform entrywise product manually + for (unsigned int pj=0; pj<rc; ++pj){ + FPLocalExp[pj]=FT[pj]; + FPLocalExp[pj]*=FPMultExp[pj]; } - } - - time.tac(); - std::cout << "took " << time.elapsed() << "sec." << std::endl; - - // PB: Verify storage improvement works (indexing etc...) - // 1) store circulant matrix - const unsigned int rc = (2*ORDER-1)*(2*ORDER-1)*(2*ORDER-1); - FReal C[rc]; - - typedef FUnifTensor<ORDER> TensorType; - unsigned int node_diff[nnodes*nnodes]; - TensorType::setNodeIdsDiff(node_diff); - unsigned int node_ids[nnodes][3]; - TensorType::setNodeIds(node_ids); - unsigned int node_ids_pairs[rc][2]; - TensorType::setNodeIdsPairs(node_ids_pairs); - - // std::cout << "2*order-1=" << 2*ORDER-1 << std::endl; - unsigned int ido=0; - for(unsigned int l=0; l<2*ORDER-1; ++l) - for(unsigned int m=0; m<2*ORDER-1; ++m) - for(unsigned int n=0; n<2*ORDER-1; ++n){ - - C[ido] - = MatrixKernel.evaluate(rootsX[node_ids_pairs[ido][0]], - rootsY[node_ids_pairs[ido][1]]); - ido++; - } - -// // Display C (gathers every values of K that need to be stored, -// // corresponds to the first line of the padded matrix (reverse order?)) -// std::cout<<"C="<<std::endl; -// for (unsigned int n=0; n<rankpad; ++n) -// std::cout<< C[ido] << ", "; -// std::cout<<std::endl; - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - // K is a block Toeplitz matrix - // i.e. a blockwise Toeplitz matrix where the block also have the Toeplitz structure. - // e.g. for ORDER=3: K=[K_{1,1} K_{1,2} K_{1,3}, where K_{i,j}=[k11 k12 k13, - // K_{2,1} K_{1,1} K_{1,2}, k21 k11 k12, - // K_{3,1} K_{2,1} K_{1,1}]; k31 k21 k11]; - // K is of size order^3 x order^3 - // (i.e. order^2 x order^2 Toeplitz blocks of size order x order), - // K is very close to be Toeplitz itself and even circulant. - // In order to actually embed K into a circulant matrix C one just - // needs to insert (ORDER-1) extra lines/columns (to each block). - -// std::cout<< "K=" <<std::endl; -// for (unsigned int i=0; i<nnodes; ++i){ -// for (unsigned int j=0; j<nnodes; ++j){ -// std::cout<< K[i*nnodes+j]<<", "; -// } -// std::cout<<std::endl; -// } -// std::cout<<std::endl; - - if(ORDER<4){// display some extra results for low orders - - // Check multi-index - std::cout<< "node_ids=" <<std::endl; - for (unsigned int i=0; i<nnodes; ++i) - std::cout<< node_ids[i][0] <<", " - << node_ids[i][1] <<", " - << node_ids[i][2] <<", "<<std::endl; - std::cout<<std::endl; - - // Check multi-index diff - std::cout<< "node_ids=" <<std::endl; - for (unsigned int i=0; i<nnodes; ++i){ - for (unsigned int j=0; j<nnodes; ++j) - std::cout<< "(" << int(node_ids[i][0]-node_ids[j][0]) <<"," - << int(node_ids[i][1]-node_ids[j][1]) <<"," - << int(node_ids[i][2]-node_ids[j][2]) <<"), "; - std::cout<<std::endl; - } - std::cout<<std::endl; - - // Check matrix node_diff - std::cout<< "node_diff=" <<std::endl; - for (unsigned int i=0; i<nnodes; ++i){ + + time.tac(); + std::cout << "took " << time.elapsed() << "sec." << std::endl; + + // std::cout<< "Transfo Padded LocalExp: "<<std::endl; + // for (unsigned int p=0; p<rc; ++p) + // std::cout<< FPLocalExp[p] << ", "; + // std::cout<<std::endl; + + Dft.applyIDFT(FPLocalExp,PLocalExp); + + // std::cout<< "Padded LocalExp: "<<std::endl; + // for (unsigned int p=0; p<rc; ++p) + // std::cout<< PLocalExp[p] << ", "; + // std::cout<<std::endl; + + // Unpad for (unsigned int j=0; j<nnodes; ++j){ - std::cout<< node_diff[i*nnodes+j] <<", "; + // if first COLUMN (T) of C is used + LocalExp[j]=PLocalExp[node_diff[nnodes-j-1]]; + // // if first ROW of C is used + // LocalExp[j]=PLocalExp[node_diff[j*nnodes]]; } - std::cout<<std::endl; - } - std::cout<<std::endl; - -// // Expected ido for the (2*ORDER-1)^3x(2*ORDER-1)^3 circulant matrix -// for (unsigned int i=0; i<rc; ++i){ -// for (unsigned int j=0; j<rc; ++j){ -// if(i>j) std::cout<< i-j-1 << ", "; -// else std::cout<< rc+i-j-1 << ", "; -// } std::cout<<std::endl; -// } std::cout<<std::endl; - -// // kernel evaluated at previous ido returns a circulant matrix -// for (unsigned int i=0; i<rc/2; ++i){ -// for (unsigned int j=0; j<rc/2; ++j){ -// if(i>j) std::cout<< C[i-j-1] << ", "; -// else std::cout<< C[rc+i-j-1] << ", "; -// } std::cout<<std::endl; -// } std::cout<<std::endl; - - }// display some extra results for low orders - - // In 1D the Zero Padding consists in - // inserting ORDER-1 zeros in the multipole exp - // in order to apply the (ORDER+ORDER-1)x(ORDER+ORDER-1) - // circulant matrix to it. - // Let us extend it to the 3D case: - FReal MultExp[nnodes]; FReal PaddedMultExp[rc]; - for (unsigned int i=0; i<nnodes; ++i) MultExp[i]=W[i]; - FReal LocalExp[nnodes]; FReal PaddedLocalExp[rc]; - FBlas::setzero(nnodes,LocalExp); - FBlas::setzero(rc,PaddedLocalExp); - -// std::cout<< "Expected LocalExp: "<<std::endl; -// for (unsigned int i=0; i<nnodes; ++i) -// std::cout<< F[i] << ", "; -// std::cout<<std::endl; - - ///////////////////////////////////////////////////////////////////////////////////// - // Application of circulant Toeplitz system in PHYSICAL SPACE - std::cout<< "Apply circulant M2L in Physical space: "; - time.tic(); - for (unsigned int i=0; i<nnodes; ++i){ - - // Pad Multipole Expansion with respect to current row - FBlas::setzero(rc,PaddedMultExp); - for (unsigned int j=0; j<nnodes; ++j) - PaddedMultExp[node_diff[i*nnodes+j]]=MultExp[j]; - -// std::cout<< "Padded MultExp for row i=" << i << ": "<<std::endl; -// for (unsigned int p=0; p<rc; ++p) -// std::cout<< PaddedMultExp[p] << ", "; -// std::cout<<std::endl; - - // Application of M2L in PHYSICAL SPACE - for (unsigned int pj=0; pj<rc; ++pj) - LocalExp[i]+=C[pj]*PaddedMultExp[pj]; - - }// end i - time.tac(); - std::cout << "took " << time.elapsed() << "sec." << std::endl; - -// std::cout<< "LocalExp via product in PHYSICAL SPACE: "<<std::endl; -// for (unsigned int p=0; p<nnodes; ++p) -// std::cout<< LocalExp[p] << ", "; -// std::cout<<std::endl; -// std::cout<<std::endl; - - ///////////////////////////////////////////////////////////////////////////////////// - // Efficient application of the Toeplitz system in FOURIER SPACE - FComplex FPMultExp[rc]; - FComplex FPLocalExp[rc]; - FReal PLocalExp[rc]; - - //for (unsigned int n=0; n<rc; ++n) FPLocalExp[n]=FComplex(0.0,0.0); - FBlas::c_setzero(rc,reinterpret_cast<FReal*>(FPLocalExp)); - - FBlas::setzero(rc,PLocalExp); - - // Init DFT - const int dimfft = 1; - const int steps[dimfft] = {rc}; - //FDft Dft(rc); // direct version - FFft<dimfft> Dft; // fast version - Dft.buildDFT(steps); - - // Get first COLUMN of K and Store in T - FReal T[rc]; - // use permutations - unsigned int perm[rc]; - for(unsigned int p=0; p<rc; ++p){ - if(p>0) perm[p]=p-1; - else perm[p]=rc+p-1; -// std::cout << "perm["<< p << "]="<< perm[p] << std::endl; - } - - for (unsigned int i=0; i<rc; ++i){ - // keep this lines commented to see what permutation accounts for: - // for (unsigned int j=0; j<rc; ++j){ -// if(i>0) T[i]=C[i-0-1]; -// else T[i]=C[rc+i-0-1]; - T[i]=C[perm[i]]; - // } - } - -// std::cout<< "First column of C[rc x rc]: "<<std::endl; -// for (unsigned int p=0; p<rc; ++p) -// std::cout<< T[p] << ", "; -// std::cout<<std::endl; - - // Apply DFT to T - FComplex FT[rc]; - // for (unsigned int n=0; n<rc; ++n) FT[n]=FComplex(0.0,0.0); - FBlas::c_setzero(rc,reinterpret_cast<FReal*>(FT)); - - // if first COLUMN (T) of C is used - Dft.applyDFT(T,FT); -// // if first ROW of C is used -// Dft.applyDFT(C,FT); - - // Pad physical MultExp - FBlas::setzero(rc,PaddedMultExp); //part of padding - for (unsigned int j=0; j<nnodes; ++j){ - // if first COLUMN (T) of C is used - PaddedMultExp[node_diff[j*nnodes]]=MultExp[j]; -// // if first ROW of C is used -// PaddedMultExp[node_diff[j]]=MultExp[j]; - } - -// std::cout<< "Padded MultExp for row i=" << i << ": "<<std::endl; -// for (unsigned int p=0; p<rc; ++p) -// std::cout<< PaddedMultExp[p] << ", "; -// std::cout<<std::endl; - - - // Set transformed MultExp to 0 - // for (unsigned int n=0; n<rc; ++n) FPMultExp[n]=FComplex(0.0,0.0); - FBlas::c_setzero(rc,reinterpret_cast<FReal*>(FPMultExp)); - - // Transform PaddedMultExp - Dft.applyDFT(PaddedMultExp,FPMultExp); - - std::cout<< "Apply M2L in Fourier space: "; - time.tic(); - - // Application of M2L in FOURIER SPACE - // > Use FMkl::c_had for hadamard product - // if mkl is used as blas (TODO otherwise use FBlas::c_had()) -// FMkl::c_had(rc,reinterpret_cast<FReal*>(FT), -// reinterpret_cast<FReal*>(FPMultExp), -// reinterpret_cast<FReal*>(FPLocalExp)); - // > or perform entrywise product manually - for (unsigned int pj=0; pj<rc; ++pj){ - FPLocalExp[pj]=FT[pj]; - FPLocalExp[pj]*=FPMultExp[pj]; - } - - time.tac(); - std::cout << "took " << time.elapsed() << "sec." << std::endl; - -// std::cout<< "Transfo Padded LocalExp: "<<std::endl; -// for (unsigned int p=0; p<rc; ++p) -// std::cout<< FPLocalExp[p] << ", "; -// std::cout<<std::endl; - - Dft.applyIDFT(FPLocalExp,PLocalExp); - -// std::cout<< "Padded LocalExp: "<<std::endl; -// for (unsigned int p=0; p<rc; ++p) -// std::cout<< PLocalExp[p] << ", "; -// std::cout<<std::endl; - - // Unpad - for (unsigned int j=0; j<nnodes; ++j){ - // if first COLUMN (T) of C is used - LocalExp[j]=PLocalExp[node_diff[nnodes-j-1]]; -// // if first ROW of C is used -// LocalExp[j]=PLocalExp[node_diff[j*nnodes]]; - } -// std::cout<< "Mask to be applied to Padded LocalExp: "<<std::endl; -// for (unsigned int j=0; j<nnodes; ++j) -// std::cout<< node_diff[nnodes-j-1] << ", "; -// std::cout<<std::endl; + // std::cout<< "Mask to be applied to Padded LocalExp: "<<std::endl; + // for (unsigned int j=0; j<nnodes; ++j) + // std::cout<< node_diff[nnodes-j-1] << ", "; + // std::cout<<std::endl; -// std::cout<< "LocalExp via product in FOURIER SPACE: "<<std::endl; -// for (unsigned int p=0; p<nnodes; ++p) -// std::cout<< LocalExp[p] << ", "; -// std::cout<<std::endl; + // std::cout<< "LocalExp via product in FOURIER SPACE: "<<std::endl; + // for (unsigned int p=0; p<nnodes; ++p) + // std::cout<< LocalExp[p] << ", "; + // std::cout<<std::endl; - ///////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////// - std::cout << "L2P (potential) ... " << std::flush; - time.tic(); - // Interpolate p_i = \sum_m^L S(x_i,\bar x_m) * F_m - S.applyL2P(cx, width, F, X.getTargets()); - std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; + std::cout << "L2P (potential) ... " << std::flush; + time.tic(); + // Interpolate p_i = \sum_m^L S(x_i,\bar x_m) * F_m + S.applyL2P(cx, width, F, X.getTargets()); + std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; - std::cout << "L2P (forces) ... " << std::flush; - time.tic(); - // Interpolate f_i = \sum_m^L P(x_i,\bar x_m) * F_m - S.applyL2PGradient(cx, width, F, X.getTargets()); - std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; + std::cout << "L2P (forces) ... " << std::flush; + time.tic(); + // Interpolate f_i = \sum_m^L P(x_i,\bar x_m) * F_m + S.applyL2PGradient(cx, width, F, X.getTargets()); + std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; - //////////////////////////////////////////////////////////////////// - // direct computation - std::cout << "Compute interactions directly ..." << std::endl; - time.tic(); + //////////////////////////////////////////////////////////////////// + // direct computation + std::cout << "Compute interactions directly ..." << std::endl; + time.tic(); - FReal* approx_f = new FReal [M * 3]; - FReal* f = new FReal [M * 3]; - FBlas::setzero(M*3, f); + FReal* approx_f = new FReal [M * 3]; + FReal* f = new FReal [M * 3]; + FBlas::setzero(M*3, f); - FReal* approx_p = new FReal[M]; - FReal* p = new FReal[M]; - FBlas::setzero(M, p); + FReal* approx_p = new FReal[M]; + FReal* p = new FReal[M]; + FBlas::setzero(M, p); - // null vectors for easy calculation of relative errors - FReal* null_p = new FReal[M]; - FBlas::setzero(M, null_p); - FReal* null_f = new FReal [M * 3]; - FBlas::setzero(M*3, null_f); + // null vectors for easy calculation of relative errors + FReal* null_p = new FReal[M]; + FBlas::setzero(M, null_p); + FReal* null_f = new FReal [M * 3]; + FBlas::setzero(M*3, null_f); - { // start direct computation - unsigned int counter = 0; + { // start direct computation + unsigned int counter = 0; + for(int idxPartX = 0 ; idxPartX < X.getSrc()->getNbParticles() ; ++idxPartX){ + const FPoint x = FPoint(X.getSrc()->getPositions()[0][idxPartX], + X.getSrc()->getPositions()[1][idxPartX], + X.getSrc()->getPositions()[2][idxPartX]); + const FReal wx = X.getSrc()->getPhysicalValues()[idxPartX]; + + for(int idxPartY = 0 ; idxPartY < Y.getSrc()->getNbParticles() ; ++idxPartY){ + const FPoint y = FPoint(Y.getSrc()->getPositions()[0][idxPartY], + Y.getSrc()->getPositions()[1][idxPartY], + Y.getSrc()->getPositions()[2][idxPartY]); + const FReal wy = Y.getSrc()->getPhysicalValues()[idxPartY]; + + const FReal one_over_r = MatrixKernel.evaluate(x, y); + // potential + p[counter] += one_over_r * wy; + // force + FPoint force(y - x); + force *= one_over_r*one_over_r*one_over_r; + f[counter*3 + 0] += force.getX() * wx * wy; + f[counter*3 + 1] += force.getY() * wx * wy; + f[counter*3 + 2] += force.getZ() * wx * wy; + } + + counter++; + } + } // end direct computation + + + time.tac(); + std::cout << "Done in " << time.elapsed() << "sec." << std::endl; + + + //////////////////////////////////////////////////////////////////// + unsigned int counter = 0; for(int idxPartX = 0 ; idxPartX < X.getSrc()->getNbParticles() ; ++idxPartX){ - const FPoint x = FPoint(X.getSrc()->getPositions()[0][idxPartX], - X.getSrc()->getPositions()[1][idxPartX], - X.getSrc()->getPositions()[2][idxPartX]); - const FReal wx = X.getSrc()->getPhysicalValues()[idxPartX]; - - for(int idxPartY = 0 ; idxPartY < Y.getSrc()->getNbParticles() ; ++idxPartY){ - const FPoint y = FPoint(Y.getSrc()->getPositions()[0][idxPartY], - Y.getSrc()->getPositions()[1][idxPartY], - Y.getSrc()->getPositions()[2][idxPartY]); - const FReal wy = Y.getSrc()->getPhysicalValues()[idxPartY]; - - const FReal one_over_r = MatrixKernel.evaluate(x, y); - // potential - p[counter] += one_over_r * wy; - // force - FPoint force(y - x); - force *= one_over_r*one_over_r*one_over_r; - f[counter*3 + 0] += force.getX() * wx * wy; - f[counter*3 + 1] += force.getY() * wx * wy; - f[counter*3 + 2] += force.getZ() * wx * wy; - } - - counter++; + approx_p[counter] = X.getSrc()->getPotentials()[idxPartX]; + const FPoint force = FPoint(X.getSrc()->getForcesX()[idxPartX], + X.getSrc()->getForcesY()[idxPartX], + X.getSrc()->getForcesZ()[idxPartX]); + approx_f[counter*3 + 0] = force.getX(); + approx_f[counter*3 + 1] = force.getY(); + approx_f[counter*3 + 2] = force.getZ(); + + counter++; } - } // end direct computation - - - time.tac(); - std::cout << "Done in " << time.elapsed() << "sec." << std::endl; - - - //////////////////////////////////////////////////////////////////// - unsigned int counter = 0; - for(int idxPartX = 0 ; idxPartX < X.getSrc()->getNbParticles() ; ++idxPartX){ - approx_p[counter] = X.getSrc()->getPotentials()[idxPartX]; - const FPoint force = FPoint(X.getSrc()->getForcesX()[idxPartX], - X.getSrc()->getForcesY()[idxPartX], - X.getSrc()->getForcesZ()[idxPartX]); - approx_f[counter*3 + 0] = force.getX(); - approx_f[counter*3 + 1] = force.getY(); - approx_f[counter*3 + 2] = force.getZ(); - - counter++; - } - -// std::cout << "Check Potential, forceX, forceY, forceZ " << std::endl; -// for(int idxPart = 0 ; idxPart < 20 ; ++idxPart){ -// std::cout << approx_p[idxPart] << ", "<< p[idxPart] << "|| "; -// std::cout << approx_f[idxPart] << ", "<< f[idxPart] << "|| "; -// std::cout << approx_f[idxPart+M] << ", "<< f[idxPart+M] << "|| "; -// std::cout << approx_f[idxPart+2*M] << ", "<< f[idxPart+2*M] << "|| "; -// std::cout << std::endl; -// } -// std::cout << std::endl; - - std::cout << "\nPotential error:" << std::endl; - std::cout << "Relative Inf error = " << FMath::FAccurater( p, approx_p, M).getRelativeInfNorm() << std::endl; - std::cout << "Relative L2 error = " << FMath::FAccurater( p, approx_p, M).getRelativeL2Norm() << std::endl; - - std::cout << "\nForce error:" << std::endl; - std::cout << "Relative Inf error = " << FMath::FAccurater( f, approx_f, M*3).getRelativeInfNorm() << std::endl; - std::cout << "Relative L2 error = " << FMath::FAccurater( f, approx_f, M*3).getRelativeL2Norm() << std::endl; - std::cout << std::endl; - - // free memory - delete [] approx_p; - delete [] p; - delete [] approx_f; - delete [] f; - - - return 0; + + // std::cout << "Check Potential, forceX, forceY, forceZ " << std::endl; + // for(int idxPart = 0 ; idxPart < 20 ; ++idxPart){ + // std::cout << approx_p[idxPart] << ", "<< p[idxPart] << "|| "; + // std::cout << approx_f[idxPart] << ", "<< f[idxPart] << "|| "; + // std::cout << approx_f[idxPart+M] << ", "<< f[idxPart+M] << "|| "; + // std::cout << approx_f[idxPart+2*M] << ", "<< f[idxPart+2*M] << "|| "; + // std::cout << std::endl; + // } + // std::cout << std::endl; + + std::cout << "\nPotential error:" << std::endl; + std::cout << "Relative Inf error = " << FMath::FAccurater( p, approx_p, M).getRelativeInfNorm() << std::endl; + std::cout << "Relative L2 error = " << FMath::FAccurater( p, approx_p, M).getRelativeL2Norm() << std::endl; + + std::cout << "\nForce error:" << std::endl; + std::cout << "Relative Inf error = " << FMath::FAccurater( f, approx_f, M*3).getRelativeInfNorm() << std::endl; + std::cout << "Relative L2 error = " << FMath::FAccurater( f, approx_f, M*3).getRelativeL2Norm() << std::endl; + std::cout << std::endl; + + // free memory + delete [] approx_p; + delete [] p; + delete [] approx_f; + delete [] f; + + + return 0; } diff --git a/Tests/Utils/testUnifTensorialInterpolator.cpp b/Tests/Utils/testUnifTensorialInterpolator.cpp index 65eb1ef35b157b4473266d6ec464370b365c1359..f543c60585359cdce62320300288cd66db7c9bd1 100755 --- a/Tests/Utils/testUnifTensorialInterpolator.cpp +++ b/Tests/Utils/testUnifTensorialInterpolator.cpp @@ -34,6 +34,7 @@ #include "Utils/FAssert.hpp" #include "Utils/FPoint.hpp" +#include "../../Src/Utils/FParameterNames.hpp" #include "Kernels/Uniform/FUnifInterpolator.hpp" #include "Kernels/Interpolation/FInterpMatrixKernel.hpp" @@ -52,594 +53,595 @@ /** * In this file we compute the interactions (direct and Unif FM-approximate) for - * a tensorial interaction kernel (R_ij) as well as the forces (comparison + * a tensorial interaction kernel (R_ij) as well as the forces (comparison * with direct computation using R_ijk kernel). */ -int main(int, char **){ - - typedef FInterpMatrixKernel_R_IJ MatrixKernelClass; - const double a = 0.0; // core width (Beware! if diff from 0. then Kernel should be NON HOMOGENEOUS !!!) - - const unsigned int ncmp = MatrixKernelClass::NCMP; - const unsigned int nrhs = MatrixKernelClass::NRHS; - const unsigned int nlhs = MatrixKernelClass::NLHS; - const unsigned int npot = MatrixKernelClass::NPOT; - - typedef FP2PParticleContainer<nrhs,nlhs> ContainerClass; - typedef FSimpleLeaf<ContainerClass> LeafClass; - - ///////////////////////What we do///////////////////////////// - std::cout << "\nTask: Compute interactions between source particles in leaf Y and target\n"; - std::cout << " particles in leaf X. Compare the fast summation K ~ Lx K Ly' with the\n"; - std::cout << " direct computation.\n" << std::endl; - ////////////////////////////////////////////////////////////// - - const FReal FRandMax = FReal(RAND_MAX); - FTic time; - - - // Leaf size - FReal width = FReal(3.723); - - //////////////////////////////////////////////////////////////////// - LeafClass X; - FPoint cx(0., 0., 0.); - const unsigned long M = 5000; - std::cout << "Fill the leaf X of width " << width - << " centered at cx=" << cx << " with M=" << M << " target particles" << std::endl; - { - - for(unsigned long i=0; i<M; ++i){ - FReal x = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getX(); - FReal y = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getY(); - FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getZ(); - // PB: need to know the actual value of NRHS (=3 here) - X.push(FPoint(x, y, z), FReal(rand())/FRandMax, FReal(rand())/FRandMax, FReal(rand())/FRandMax); +int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, "Test the uniform tensorial interpolator (only the code is interesting)"); + + typedef FInterpMatrixKernel_R_IJ MatrixKernelClass; + const double a = 0.0; // core width (Beware! if diff from 0. then Kernel should be NON HOMOGENEOUS !!!) + + const unsigned int ncmp = MatrixKernelClass::NCMP; + const unsigned int nrhs = MatrixKernelClass::NRHS; + const unsigned int nlhs = MatrixKernelClass::NLHS; + const unsigned int npot = MatrixKernelClass::NPOT; + + typedef FP2PParticleContainer<nrhs,nlhs> ContainerClass; + typedef FSimpleLeaf<ContainerClass> LeafClass; + + ///////////////////////What we do///////////////////////////// + std::cout << "\nTask: Compute interactions between source particles in leaf Y and target\n"; + std::cout << " particles in leaf X. Compare the fast summation K ~ Lx K Ly' with the\n"; + std::cout << " direct computation.\n" << std::endl; + ////////////////////////////////////////////////////////////// + + const FReal FRandMax = FReal(RAND_MAX); + FTic time; + + + // Leaf size + FReal width = FReal(3.723); + + //////////////////////////////////////////////////////////////////// + LeafClass X; + FPoint cx(0., 0., 0.); + const unsigned long M = 5000; + std::cout << "Fill the leaf X of width " << width + << " centered at cx=" << cx << " with M=" << M << " target particles" << std::endl; + { + + for(unsigned long i=0; i<M; ++i){ + FReal x = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getX(); + FReal y = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getY(); + FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getZ(); + // PB: need to know the actual value of NRHS (=3 here) + X.push(FPoint(x, y, z), FReal(rand())/FRandMax, FReal(rand())/FRandMax, FReal(rand())/FRandMax); + } } - } - //////////////////////////////////////////////////////////////////// - LeafClass Y; + //////////////////////////////////////////////////////////////////// + LeafClass Y; FPoint cy(FReal(2.)*width, 0., 0.); - //FPoint cy(FReal(2.)*width, FReal(2.)*width, 0.); - - const unsigned long N = 5000; - std::cout << "Fill the leaf Y of width " << width - << " centered at cy=" << cy << " with N=" << N << " source particles" << std::endl; - { - for(unsigned long i=0; i<N; ++i){ - FReal x = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getX(); - FReal y = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getY(); - FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getZ(); - // PB: need to know the actual value of NRHS (=3 here) - Y.push(FPoint(x, y, z), FReal(rand())/FRandMax, FReal(rand())/FRandMax, FReal(rand())/FRandMax); + //FPoint cy(FReal(2.)*width, FReal(2.)*width, 0.); + + const unsigned long N = 5000; + std::cout << "Fill the leaf Y of width " << width + << " centered at cy=" << cy << " with N=" << N << " source particles" << std::endl; + { + for(unsigned long i=0; i<N; ++i){ + FReal x = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getX(); + FReal y = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getY(); + FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getZ(); + // PB: need to know the actual value of NRHS (=3 here) + Y.push(FPoint(x, y, z), FReal(rand())/FRandMax, FReal(rand())/FRandMax, FReal(rand())/FRandMax); + } } - } - - - - //////////////////////////////////////////////////////////////////// - // approximative computation - const unsigned int ORDER = 6; - const unsigned int nnodes = TensorTraits<ORDER>::nnodes; - typedef FUnifInterpolator<ORDER,MatrixKernelClass> InterpolatorClass; - InterpolatorClass S; - MatrixKernelClass MatrixKernel; - - std::cout << "\nCompute interactions approximatively, interpolation order = " << ORDER << " ..." << std::endl; - - std::cout << "\nP2M ... " << std::flush; - time.tic(); - // Anterpolate: W_n = \sum_j^N S(y_j,\bar y_n) * w_j - FReal W[nrhs*nnodes]; // multipole expansion - // tensorial case interpolate same Y for each component - S.applyP2M(cy, width, W, Y.getSrc()); // the multipole expansions are set to 0 in S.applyP2M - std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; - - std::cout << "M2L ... " << std::flush; - time.tic(); - // Multipole to local: F_m = \sum_n^L K(\bar x_m, \bar y_n) * W_n - FPoint rootsX[nnodes], rootsY[nnodes]; - FUnifTensor<ORDER>::setRoots(cx, width, rootsX); - FUnifTensor<ORDER>::setRoots(cy, width, rootsY); - - FReal F[nlhs*nnodes]; // local expansion - for (unsigned int i=0; i<nnodes*nlhs; ++i) F[i] = FReal(0.); - - for (unsigned int i=0; i<nnodes; ++i) { - for (unsigned int j=0; j<nnodes; ++j){ - - for (unsigned int idxLhs=0; idxLhs<nlhs; ++idxLhs){ - unsigned int idxRhs = idxLhs % npot; - unsigned int d = MatrixKernel.getPosition(idxLhs); - F[i+idxLhs*nnodes] += MatrixKernelClass(a,d).evaluate(rootsX[i], rootsY[j]) * W[j+idxRhs*nnodes]; - } + + //////////////////////////////////////////////////////////////////// + // approximative computation + const unsigned int ORDER = 6; + const unsigned int nnodes = TensorTraits<ORDER>::nnodes; + typedef FUnifInterpolator<ORDER,MatrixKernelClass> InterpolatorClass; + InterpolatorClass S; + MatrixKernelClass MatrixKernel; + + std::cout << "\nCompute interactions approximatively, interpolation order = " << ORDER << " ..." << std::endl; + + std::cout << "\nP2M ... " << std::flush; + time.tic(); + // Anterpolate: W_n = \sum_j^N S(y_j,\bar y_n) * w_j + FReal W[nrhs*nnodes]; // multipole expansion + // tensorial case interpolate same Y for each component + S.applyP2M(cy, width, W, Y.getSrc()); // the multipole expansions are set to 0 in S.applyP2M + std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; + + std::cout << "M2L ... " << std::flush; + time.tic(); + // Multipole to local: F_m = \sum_n^L K(\bar x_m, \bar y_n) * W_n + FPoint rootsX[nnodes], rootsY[nnodes]; + FUnifTensor<ORDER>::setRoots(cx, width, rootsX); + FUnifTensor<ORDER>::setRoots(cy, width, rootsY); + + FReal F[nlhs*nnodes]; // local expansion + for (unsigned int i=0; i<nnodes*nlhs; ++i) F[i] = FReal(0.); + + for (unsigned int i=0; i<nnodes; ++i) { + for (unsigned int j=0; j<nnodes; ++j){ + + for (unsigned int idxLhs=0; idxLhs<nlhs; ++idxLhs){ + unsigned int idxRhs = idxLhs % npot; + unsigned int d = MatrixKernel.getPosition(idxLhs); + + F[i+idxLhs*nnodes] += MatrixKernelClass(a,d).evaluate(rootsX[i], rootsY[j]) * W[j+idxRhs*nnodes]; + + } + } } - } - std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; - -// std::cout<< "F via direct applyM2L: "<<std::endl; -// for (unsigned int d=0; d<nlhs; ++d){ -// for (unsigned int i=0; i<nnodes; ++i) -// std::cout<< F[i+d*nnodes] << ", "; -// std::cout<<std::endl; -// } -// std::cout<<std::endl; - - //////////////////////////////////////////////////////////////////////////// - // Store M2L in K and apply K - FReal K[ncmp*nnodes*nnodes]; // local expansion - for (unsigned int i=0; i<nnodes; ++i) { - for (unsigned int j=0; j<nnodes; ++j){ - - for (unsigned int d=0; d<ncmp; ++d){ - K[d*nnodes*nnodes+i*nnodes+j] = MatrixKernelClass(a,d).evaluate(rootsX[i], rootsY[j]); - } + std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; + + // std::cout<< "F via direct applyM2L: "<<std::endl; + // for (unsigned int d=0; d<nlhs; ++d){ + // for (unsigned int i=0; i<nnodes; ++i) + // std::cout<< F[i+d*nnodes] << ", "; + // std::cout<<std::endl; + // } + // std::cout<<std::endl; + + //////////////////////////////////////////////////////////////////////////// + // Store M2L in K and apply K + FReal K[ncmp*nnodes*nnodes]; // local expansion + for (unsigned int i=0; i<nnodes; ++i) { + for (unsigned int j=0; j<nnodes; ++j){ + + for (unsigned int d=0; d<ncmp; ++d){ + K[d*nnodes*nnodes+i*nnodes+j] = MatrixKernelClass(a,d).evaluate(rootsX[i], rootsY[j]); + } + } } - } - std::cout<< "Apply M2L in usual sense: "; - time.tic(); - for (unsigned int i=0; i<nnodes*nlhs; ++i) F[i] = FReal(0.); + std::cout<< "Apply M2L in usual sense: "; + time.tic(); + for (unsigned int i=0; i<nnodes*nlhs; ++i) F[i] = FReal(0.); - for (unsigned int i=0; i<nnodes; ++i) - for (unsigned int j=0; j<nnodes; ++j){ + for (unsigned int i=0; i<nnodes; ++i) + for (unsigned int j=0; j<nnodes; ++j){ - for (unsigned int idxLhs=0; idxLhs<nlhs; ++idxLhs){ - unsigned int idxRhs = idxLhs % npot; - unsigned int d = MatrixKernel.getPosition(idxLhs); + for (unsigned int idxLhs=0; idxLhs<nlhs; ++idxLhs){ + unsigned int idxRhs = idxLhs % npot; + unsigned int d = MatrixKernel.getPosition(idxLhs); + + F[i+idxLhs*nnodes] += K[d*nnodes*nnodes+i*nnodes+j] * W[j+idxRhs*nnodes]; + + } + } + + time.tac(); + std::cout << "took " << time.elapsed() << "sec." << std::endl; + + // std::cout<< "F via store and applyM2L: "<<std::endl; + // for (unsigned int d=0; d<nlhs; ++d){ + // for (unsigned int i=0; i<nnodes; ++i) + // std::cout<< F[i+d*nnodes] << ", "; + // std::cout<<std::endl; + // } + // std::cout<<std::endl; + + ///////////////////////////////////////////////////////////////////////////////////// + // PB: Verify storage improvement works (indexing etc...) + // 1) store circulant matrix + const unsigned int rc = (2*ORDER-1)*(2*ORDER-1)*(2*ORDER-1); + FReal C[ncmp*rc]; + + typedef FUnifTensor<ORDER> TensorType; + unsigned int node_diff[nnodes*nnodes]; + TensorType::setNodeIdsDiff(node_diff); + unsigned int node_ids_pairs[rc][2]; + TensorType::setNodeIdsPairs(node_ids_pairs); + + unsigned int ido=0; + + for(unsigned int l=0; l<2*ORDER-1; ++l) + for(unsigned int m=0; m<2*ORDER-1; ++m) + for(unsigned int n=0; n<2*ORDER-1; ++n){ - F[i+idxLhs*nnodes] += K[d*nnodes*nnodes+i*nnodes+j] * W[j+idxRhs*nnodes]; + for (unsigned int d=0; d<ncmp; ++d){ + C[d*rc + ido] + = MatrixKernelClass(a,d).evaluate(rootsX[node_ids_pairs[ido][0]], + rootsY[node_ids_pairs[ido][1]]); + } + + ido++; + } + + // // Display C (gathers every values of K that need to be stored, + // // corresponds to the first line of the padded matrix (reverse order?)) + // std::cout<<"C="<<std::endl; + // for (unsigned int d=0; d<ncmp; ++d){ + // for (unsigned int n=0; n<rc; ++n) + // std::cout<< C[n + d*rc] << ", "; + // std::cout<<std::endl; + // } + // std::cout<<std::endl; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // K is a block Toeplitz matrix + // i.e. a blockwise Toeplitz matrix where the block also have the Toeplitz structure. + // e.g. for ORDER=3: K=[K_{1,1} K_{1,2} K_{1,3}, where K_{i,j}=[k11 k12 k13, + // K_{2,1} K_{1,1} K_{1,2}, k21 k11 k12, + // K_{3,1} K_{2,1} K_{1,1}]; k31 k21 k11]; + // K is of size order^3 x order^3 + // (i.e. order^2 x order^2 Toeplitz blocks of size order x order), + // K is very close to be Toeplitz itself and even circulant. + // In order to actually embed K into a circulant matrix C one just + // needs to insert (ORDER-1) extra lines/columns (to each block). + + // std::cout<< "K=" <<std::endl; + // for (unsigned int i=0; i<nnodes; ++i){ + // for (unsigned int j=0; j<nnodes; ++j){ + // std::cout<< K[i*nnodes+j]<<", "; + // } + // std::cout<<std::endl; + // } + // std::cout<<std::endl; + + // // Check matrix node_diff + // std::cout<< "node_diff=" <<std::endl; + // for (unsigned int i=0; i<nnodes; ++i){ + // for (unsigned int j=0; j<nnodes; ++j){ + // std::cout<< node_diff[i*nnodes+j] <<", "; + // } + // std::cout<<std::endl; + // } + // std::cout<<std::endl; + + // // Expected ido for the (2*ORDER-1)^3x(2*ORDER-1)^3 circulant matrix + // for (unsigned int i=0; i<rc; ++i){ + // for (unsigned int j=0; j<rc; ++j){ + // if(i>j) std::cout<< i-j-1 << ", "; + // else std::cout<< rc+i-j-1 << ", "; + // } std::cout<<std::endl; + // } std::cout<<std::endl; + + // // kernel evaluated at previous ido returns a circulant matrix + // for (unsigned int i=0; i<rc/2; ++i){ + // for (unsigned int j=0; j<rc/2; ++j){ + // if(i>j) std::cout<< C[i-j-1] << ", "; + // else std::cout<< C[rc+i-j-1] << ", "; + // } std::cout<<std::endl; + // } std::cout<<std::endl; + + // In 1D the Zero Padding consists in + // inserting ORDER-1 zeros in the multipole exp + // in order to apply the (ORDER+ORDER-1)x(ORDER+ORDER-1) + // circulant matrix to it. + // Let us extend it to the 3D case: + FReal MultExp[nrhs*nnodes]; FReal PaddedMultExp[nrhs*rc]; + for (unsigned int i=0; i<nrhs*nnodes; ++i) MultExp[i]=W[i]; + FReal LocalExp[nlhs*nnodes]; FReal PaddedLocalExp[nlhs*rc]; + FBlas::setzero(nlhs*nnodes,LocalExp); + FBlas::setzero(nlhs*rc,PaddedLocalExp); + + // std::cout<< "Expected LocalExp: "<<std::endl; + // for (unsigned int d=0; d<nlhs; ++d){ + // for (unsigned int i=0; i<nnodes; ++i) + // std::cout<< F[i+d*nnodes] << ", "; + // std::cout<<std::endl; + // } + + ///////////////////////////////////////////////////////////////////////////////////// + // Application of circulant Toeplitz system in PHYSICAL SPACE + std::cout<< "Apply circulant M2L in Physical space: "; + time.tic(); + for (unsigned int i=0; i<nnodes; ++i){ + + // Pad Multipole Expansion with respect to current row + FBlas::setzero(nrhs*rc,PaddedMultExp); + for (unsigned int j=0; j<nnodes; ++j) + for (unsigned int d=0; d<nrhs; ++d) + PaddedMultExp[node_diff[i*nnodes+j] + d*rc]=MultExp[j + d*nnodes]; + + // std::cout<< "Padded MultExp for row i=" << i << ": "<<std::endl; + // for (unsigned int p=0; p<rc; ++p) + // std::cout<< PaddedMultExp[p] << ", "; + // std::cout<<std::endl; + + // Application of M2L in PHYSICAL SPACE + for (unsigned int pj=0; pj<rc; ++pj) + for (unsigned int idxLhs=0; idxLhs<nlhs; ++idxLhs){ + unsigned int idxRhs = idxLhs % npot; + unsigned int d = MatrixKernel.getPosition(idxLhs); + + LocalExp[i + idxLhs*nnodes]+=C[pj + d*rc]*PaddedMultExp[pj + idxRhs*rc]; + + } + + }// end i + time.tac(); + std::cout << "took " << time.elapsed() << "sec." << std::endl; + + // std::cout<< "LocalExp via product in PHYSICAL SPACE: "<<std::endl; + // for (unsigned int d=0; d<nlhs; ++d){ + // for (unsigned int i=0; i<nnodes; ++i) + // std::cout<< LocalExp[i+d*nnodes] << ", "; + // std::cout<<std::endl; + // } + // std::cout<<std::endl; + + ///////////////////////////////////////////////////////////////////////////////////// + // Efficient application of the Toeplitz system in FOURIER SPACE + + // Init DFT + const int dimfft = 1; + const int steps[dimfft] = {rc}; + //FDft Dft(rc); // direct version + FFft<dimfft> Dft; // fast version + Dft.buildDFT(steps); + + // Get first COLUMN of K and Store in T + FReal T[ncmp*rc]; + // use permutations + unsigned int perm[rc]; + for(unsigned int p=0; p<rc; ++p){ + if(p>0) perm[p]=p-1; + else perm[p]=rc+p-1; + // std::cout << "perm["<< p << "]="<< perm[p] << std::endl; + } + + for (unsigned int i=0; i<rc; ++i){ + // keep this lines commented to see what permutation accounts for: + // for (unsigned int j=0; j<rc; ++j){ + // if(i>0) T[i]=C[i-0-1]; + // else T[i]=C[rc+i-0-1]; + for (unsigned int d=0; d<ncmp; ++d) + T[i + d*rc]=C[perm[i] + d*rc]; + // } } - } - - time.tac(); - std::cout << "took " << time.elapsed() << "sec." << std::endl; - -// std::cout<< "F via store and applyM2L: "<<std::endl; -// for (unsigned int d=0; d<nlhs; ++d){ -// for (unsigned int i=0; i<nnodes; ++i) -// std::cout<< F[i+d*nnodes] << ", "; -// std::cout<<std::endl; -// } -// std::cout<<std::endl; - - ///////////////////////////////////////////////////////////////////////////////////// - // PB: Verify storage improvement works (indexing etc...) - // 1) store circulant matrix - const unsigned int rc = (2*ORDER-1)*(2*ORDER-1)*(2*ORDER-1); - FReal C[ncmp*rc]; - - typedef FUnifTensor<ORDER> TensorType; - unsigned int node_diff[nnodes*nnodes]; - TensorType::setNodeIdsDiff(node_diff); - unsigned int node_ids_pairs[rc][2]; - TensorType::setNodeIdsPairs(node_ids_pairs); - - unsigned int ido=0; - - for(unsigned int l=0; l<2*ORDER-1; ++l) - for(unsigned int m=0; m<2*ORDER-1; ++m) - for(unsigned int n=0; n<2*ORDER-1; ++n){ - - for (unsigned int d=0; d<ncmp; ++d){ - - C[d*rc + ido] - = MatrixKernelClass(a,d).evaluate(rootsX[node_ids_pairs[ido][0]], - rootsY[node_ids_pairs[ido][1]]); + + // std::cout<< "First column of C[rc x rc]: "<<std::endl; + // for (unsigned int p=0; p<rc; ++p) + // std::cout<< T[p] << ", "; + // std::cout<<std::endl; + + // Apply DFT to T + FComplex FT[ncmp*rc]; + // for (unsigned int n=0; n<rc; ++n) FT[n]=FComplex(0.0,0.0); + FBlas::c_setzero(ncmp*rc,reinterpret_cast<FReal*>(FT)); + + // if first COLUMN (T) of C is used + for (unsigned int d=0; d<ncmp; ++d) + Dft.applyDFT(T+d*rc,FT+d*rc); + // // if first ROW of C is used + // Dft.applyDFT(C,FT); + + FComplex FPMultExp[nrhs*rc]; + FComplex FPLocalExp[nlhs*rc]; + FReal PLocalExp[nlhs*rc]; + + //for (unsigned int n=0; n<rc; ++n) FPLocalExp[n]=FComplex(0.0,0.0); + FBlas::c_setzero(nlhs*rc,reinterpret_cast<FReal*>(FPLocalExp)); + + FBlas::setzero(nlhs*rc,PLocalExp); + + // Pad physical MultExp + FBlas::setzero(nrhs*rc,PaddedMultExp); //part of padding + for (unsigned int idRhs=0; idRhs<nrhs; ++idRhs) + for (unsigned int j=0; j<nnodes; ++j){ + // if first COLUMN (T) of C is used + PaddedMultExp[node_diff[j*nnodes]+idRhs*rc]=MultExp[j+idRhs*nnodes]; + // // if first ROW of C is used + // PaddedMultExp[node_diff[j]]=MultExp[j]; } - - ido++; - } - -// // Display C (gathers every values of K that need to be stored, -// // corresponds to the first line of the padded matrix (reverse order?)) -// std::cout<<"C="<<std::endl; -// for (unsigned int d=0; d<ncmp; ++d){ -// for (unsigned int n=0; n<rc; ++n) -// std::cout<< C[n + d*rc] << ", "; -// std::cout<<std::endl; -// } -// std::cout<<std::endl; - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - // K is a block Toeplitz matrix - // i.e. a blockwise Toeplitz matrix where the block also have the Toeplitz structure. - // e.g. for ORDER=3: K=[K_{1,1} K_{1,2} K_{1,3}, where K_{i,j}=[k11 k12 k13, - // K_{2,1} K_{1,1} K_{1,2}, k21 k11 k12, - // K_{3,1} K_{2,1} K_{1,1}]; k31 k21 k11]; - // K is of size order^3 x order^3 - // (i.e. order^2 x order^2 Toeplitz blocks of size order x order), - // K is very close to be Toeplitz itself and even circulant. - // In order to actually embed K into a circulant matrix C one just - // needs to insert (ORDER-1) extra lines/columns (to each block). - -// std::cout<< "K=" <<std::endl; -// for (unsigned int i=0; i<nnodes; ++i){ -// for (unsigned int j=0; j<nnodes; ++j){ -// std::cout<< K[i*nnodes+j]<<", "; -// } -// std::cout<<std::endl; -// } -// std::cout<<std::endl; - -// // Check matrix node_diff -// std::cout<< "node_diff=" <<std::endl; -// for (unsigned int i=0; i<nnodes; ++i){ -// for (unsigned int j=0; j<nnodes; ++j){ -// std::cout<< node_diff[i*nnodes+j] <<", "; -// } -// std::cout<<std::endl; -// } -// std::cout<<std::endl; - -// // Expected ido for the (2*ORDER-1)^3x(2*ORDER-1)^3 circulant matrix -// for (unsigned int i=0; i<rc; ++i){ -// for (unsigned int j=0; j<rc; ++j){ -// if(i>j) std::cout<< i-j-1 << ", "; -// else std::cout<< rc+i-j-1 << ", "; -// } std::cout<<std::endl; -// } std::cout<<std::endl; - -// // kernel evaluated at previous ido returns a circulant matrix -// for (unsigned int i=0; i<rc/2; ++i){ -// for (unsigned int j=0; j<rc/2; ++j){ -// if(i>j) std::cout<< C[i-j-1] << ", "; -// else std::cout<< C[rc+i-j-1] << ", "; -// } std::cout<<std::endl; -// } std::cout<<std::endl; - - // In 1D the Zero Padding consists in - // inserting ORDER-1 zeros in the multipole exp - // in order to apply the (ORDER+ORDER-1)x(ORDER+ORDER-1) - // circulant matrix to it. - // Let us extend it to the 3D case: - FReal MultExp[nrhs*nnodes]; FReal PaddedMultExp[nrhs*rc]; - for (unsigned int i=0; i<nrhs*nnodes; ++i) MultExp[i]=W[i]; - FReal LocalExp[nlhs*nnodes]; FReal PaddedLocalExp[nlhs*rc]; - FBlas::setzero(nlhs*nnodes,LocalExp); - FBlas::setzero(nlhs*rc,PaddedLocalExp); - -// std::cout<< "Expected LocalExp: "<<std::endl; -// for (unsigned int d=0; d<nlhs; ++d){ -// for (unsigned int i=0; i<nnodes; ++i) -// std::cout<< F[i+d*nnodes] << ", "; -// std::cout<<std::endl; -// } - - ///////////////////////////////////////////////////////////////////////////////////// - // Application of circulant Toeplitz system in PHYSICAL SPACE - std::cout<< "Apply circulant M2L in Physical space: "; - time.tic(); - for (unsigned int i=0; i<nnodes; ++i){ - - // Pad Multipole Expansion with respect to current row - FBlas::setzero(nrhs*rc,PaddedMultExp); - for (unsigned int j=0; j<nnodes; ++j) - for (unsigned int d=0; d<nrhs; ++d) - PaddedMultExp[node_diff[i*nnodes+j] + d*rc]=MultExp[j + d*nnodes]; - -// std::cout<< "Padded MultExp for row i=" << i << ": "<<std::endl; -// for (unsigned int p=0; p<rc; ++p) -// std::cout<< PaddedMultExp[p] << ", "; -// std::cout<<std::endl; - - // Application of M2L in PHYSICAL SPACE - for (unsigned int pj=0; pj<rc; ++pj) - for (unsigned int idxLhs=0; idxLhs<nlhs; ++idxLhs){ + + // std::cout<< "Padded MultExp: "<<std::endl; + // for (unsigned int p=0; p<rc; ++p) + // std::cout<< PaddedMultExp[p] << ", "; + // std::cout<<std::endl; + + + // Set transformed MultExp to 0 + // for (unsigned int n=0; n<rc; ++n) FPMultExp[n]=FComplex(0.0,0.0); + FBlas::c_setzero(nrhs*rc,reinterpret_cast<FReal*>(FPMultExp)); + + // Transform PaddedMultExp + for (unsigned int idxRhs=0; idxRhs<nrhs; ++idxRhs) // apply nrhs 1 dimensionnal FFT + Dft.applyDFT(PaddedMultExp+idxRhs*rc,FPMultExp+idxRhs*rc); + + std::cout<< "Apply M2L in Fourier space: "; + time.tic(); + + // Application of M2L in FOURIER SPACE + // > Use FMkl::c_had for hadamard product + // if mkl is used as blas (TODO otherwise use FBlas::c_had()) + // FMkl::c_had(rc,reinterpret_cast<FReal*>(FT), + // reinterpret_cast<FReal*>(FPMultExp), + // reinterpret_cast<FReal*>(FPLocalExp)); + // > or perform entrywise product manually + FComplex tmpFX; + for (unsigned int idxLhs=0; idxLhs<nlhs; ++idxLhs){ unsigned int idxRhs = idxLhs % npot; unsigned int d = MatrixKernel.getPosition(idxLhs); - LocalExp[i + idxLhs*nnodes]+=C[pj + d*rc]*PaddedMultExp[pj + idxRhs*rc]; - - } - - }// end i - time.tac(); - std::cout << "took " << time.elapsed() << "sec." << std::endl; - -// std::cout<< "LocalExp via product in PHYSICAL SPACE: "<<std::endl; -// for (unsigned int d=0; d<nlhs; ++d){ -// for (unsigned int i=0; i<nnodes; ++i) -// std::cout<< LocalExp[i+d*nnodes] << ", "; -// std::cout<<std::endl; -// } -// std::cout<<std::endl; - - ///////////////////////////////////////////////////////////////////////////////////// - // Efficient application of the Toeplitz system in FOURIER SPACE - - // Init DFT - const int dimfft = 1; - const int steps[dimfft] = {rc}; - //FDft Dft(rc); // direct version - FFft<dimfft> Dft; // fast version - Dft.buildDFT(steps); - - // Get first COLUMN of K and Store in T - FReal T[ncmp*rc]; - // use permutations - unsigned int perm[rc]; - for(unsigned int p=0; p<rc; ++p){ - if(p>0) perm[p]=p-1; - else perm[p]=rc+p-1; -// std::cout << "perm["<< p << "]="<< perm[p] << std::endl; - } - - for (unsigned int i=0; i<rc; ++i){ - // keep this lines commented to see what permutation accounts for: - // for (unsigned int j=0; j<rc; ++j){ -// if(i>0) T[i]=C[i-0-1]; -// else T[i]=C[rc+i-0-1]; - for (unsigned int d=0; d<ncmp; ++d) - T[i + d*rc]=C[perm[i] + d*rc]; - // } - } - -// std::cout<< "First column of C[rc x rc]: "<<std::endl; -// for (unsigned int p=0; p<rc; ++p) -// std::cout<< T[p] << ", "; -// std::cout<<std::endl; - - // Apply DFT to T - FComplex FT[ncmp*rc]; - // for (unsigned int n=0; n<rc; ++n) FT[n]=FComplex(0.0,0.0); - FBlas::c_setzero(ncmp*rc,reinterpret_cast<FReal*>(FT)); - - // if first COLUMN (T) of C is used - for (unsigned int d=0; d<ncmp; ++d) - Dft.applyDFT(T+d*rc,FT+d*rc); -// // if first ROW of C is used -// Dft.applyDFT(C,FT); - - FComplex FPMultExp[nrhs*rc]; - FComplex FPLocalExp[nlhs*rc]; - FReal PLocalExp[nlhs*rc]; - - //for (unsigned int n=0; n<rc; ++n) FPLocalExp[n]=FComplex(0.0,0.0); - FBlas::c_setzero(nlhs*rc,reinterpret_cast<FReal*>(FPLocalExp)); - - FBlas::setzero(nlhs*rc,PLocalExp); - - // Pad physical MultExp - FBlas::setzero(nrhs*rc,PaddedMultExp); //part of padding - for (unsigned int idRhs=0; idRhs<nrhs; ++idRhs) - for (unsigned int j=0; j<nnodes; ++j){ - // if first COLUMN (T) of C is used - PaddedMultExp[node_diff[j*nnodes]+idRhs*rc]=MultExp[j+idRhs*nnodes]; -// // if first ROW of C is used -// PaddedMultExp[node_diff[j]]=MultExp[j]; + for (unsigned int pj=0; pj<rc; ++pj){ + tmpFX=FT[pj + d*rc]; + tmpFX*=FPMultExp[pj+idxRhs*rc]; + FPLocalExp[pj+idxLhs*rc]+=tmpFX; // add new contribution +RijYj + } + } + time.tac(); + std::cout << "took " << time.elapsed() << "sec." << std::endl; + + // std::cout<< "Transfo Padded LocalExp: "<<std::endl; + // for (unsigned int p=0; p<rc; ++p) + // std::cout<< FPLocalExp[p] << ", "; + // std::cout<<std::endl; + + for (unsigned int idxLhs=0; idxLhs<nlhs; ++idxLhs) // apply nrhs 1 dimensionnal FFT + Dft.applyIDFT(FPLocalExp+idxLhs*rc,PLocalExp+idxLhs*rc); + + // std::cout<< "Padded LocalExp: "<<std::endl; + // for (unsigned int p=0; p<rc; ++p) + // std::cout<< PLocalExp[p] << ", "; + // std::cout<<std::endl; + + // Unpad + for (unsigned int idLhs=0; idLhs<nlhs; ++idLhs) + for (unsigned int j=0; j<nnodes; ++j){ + // if first COLUMN (T) of C is used + LocalExp[j+idLhs*nnodes]=PLocalExp[node_diff[nnodes-j-1]+idLhs*rc]; + // // if first ROW of C is used + // LocalExp[j]=PLocalExp[node_diff[j*nnodes]]; + } -// std::cout<< "Padded MultExp: "<<std::endl; -// for (unsigned int p=0; p<rc; ++p) -// std::cout<< PaddedMultExp[p] << ", "; -// std::cout<<std::endl; - - - // Set transformed MultExp to 0 - // for (unsigned int n=0; n<rc; ++n) FPMultExp[n]=FComplex(0.0,0.0); - FBlas::c_setzero(nrhs*rc,reinterpret_cast<FReal*>(FPMultExp)); - - // Transform PaddedMultExp - for (unsigned int idxRhs=0; idxRhs<nrhs; ++idxRhs) // apply nrhs 1 dimensionnal FFT - Dft.applyDFT(PaddedMultExp+idxRhs*rc,FPMultExp+idxRhs*rc); - - std::cout<< "Apply M2L in Fourier space: "; - time.tic(); - - // Application of M2L in FOURIER SPACE - // > Use FMkl::c_had for hadamard product - // if mkl is used as blas (TODO otherwise use FBlas::c_had()) -// FMkl::c_had(rc,reinterpret_cast<FReal*>(FT), -// reinterpret_cast<FReal*>(FPMultExp), -// reinterpret_cast<FReal*>(FPLocalExp)); - // > or perform entrywise product manually - FComplex tmpFX; - for (unsigned int idxLhs=0; idxLhs<nlhs; ++idxLhs){ - unsigned int idxRhs = idxLhs % npot; - unsigned int d = MatrixKernel.getPosition(idxLhs); - - for (unsigned int pj=0; pj<rc; ++pj){ - tmpFX=FT[pj + d*rc]; - tmpFX*=FPMultExp[pj+idxRhs*rc]; - FPLocalExp[pj+idxLhs*rc]+=tmpFX; // add new contribution +RijYj + // std::cout<< "Mask to be applied to Padded LocalExp: "<<std::endl; + // for (unsigned int j=0; j<nnodes; ++j) + // std::cout<< node_diff[nnodes-j-1] << ", "; + // std::cout<<std::endl; + + // std::cout<< "LocalExp via product in FOURIER SPACE: "<<std::endl; + // for (unsigned int d=0; d<nlhs; ++d){ + // for (unsigned int p=0; p<nnodes; ++p) + // std::cout<< LocalExp[p + d*nnodes] << ", "; + // std::cout<<std::endl; + // } + // std::cout<<std::endl; + + + ///////////////////////////////////////////////////////////////////////////////////// + + std::cout << "L2P (potential) ... " << std::flush; + time.tic(); + // Interpolate p_i = \sum_m^L S(x_i,\bar x_m) * F_m + S.applyL2P(cx, width, F, X.getTargets()); + std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; + + std::cout << "L2P (forces) ... " << std::flush; + time.tic(); + // Interpolate f_i = \sum_m^L P(x_i,\bar x_m) * F_m + S.applyL2PGradient(cx, width, F, X.getTargets()); + std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; + + //////////////////////////////////////////////////////////////////// + // direct computation + std::cout << "Compute interactions directly ..." << std::endl; + time.tic(); + + FReal** approx_f = new FReal* [npot]; + FReal** f = new FReal* [npot]; + for (unsigned int i=0; i<npot; ++i){ + approx_f[i] = new FReal [M * 3]; + f[i] = new FReal [M * 3]; + FBlas::setzero(M*3, f[i]); } - } - time.tac(); - std::cout << "took " << time.elapsed() << "sec." << std::endl; - -// std::cout<< "Transfo Padded LocalExp: "<<std::endl; -// for (unsigned int p=0; p<rc; ++p) -// std::cout<< FPLocalExp[p] << ", "; -// std::cout<<std::endl; - - for (unsigned int idxLhs=0; idxLhs<nlhs; ++idxLhs) // apply nrhs 1 dimensionnal FFT - Dft.applyIDFT(FPLocalExp+idxLhs*rc,PLocalExp+idxLhs*rc); - -// std::cout<< "Padded LocalExp: "<<std::endl; -// for (unsigned int p=0; p<rc; ++p) -// std::cout<< PLocalExp[p] << ", "; -// std::cout<<std::endl; - - // Unpad - for (unsigned int idLhs=0; idLhs<nlhs; ++idLhs) - for (unsigned int j=0; j<nnodes; ++j){ - // if first COLUMN (T) of C is used - LocalExp[j+idLhs*nnodes]=PLocalExp[node_diff[nnodes-j-1]+idLhs*rc]; -// // if first ROW of C is used -// LocalExp[j]=PLocalExp[node_diff[j*nnodes]]; + FReal** approx_p = new FReal* [npot]; + FReal** p = new FReal* [npot]; + for (unsigned int i=0; i<npot; ++i){ + approx_p[i] = new FReal [M]; + p[i] = new FReal [M]; + FBlas::setzero(M, p[i]); } -// std::cout<< "Mask to be applied to Padded LocalExp: "<<std::endl; -// for (unsigned int j=0; j<nnodes; ++j) -// std::cout<< node_diff[nnodes-j-1] << ", "; -// std::cout<<std::endl; - -// std::cout<< "LocalExp via product in FOURIER SPACE: "<<std::endl; -// for (unsigned int d=0; d<nlhs; ++d){ -// for (unsigned int p=0; p<nnodes; ++p) -// std::cout<< LocalExp[p + d*nnodes] << ", "; -// std::cout<<std::endl; -// } -// std::cout<<std::endl; - - - ///////////////////////////////////////////////////////////////////////////////////// - - std::cout << "L2P (potential) ... " << std::flush; - time.tic(); - // Interpolate p_i = \sum_m^L S(x_i,\bar x_m) * F_m - S.applyL2P(cx, width, F, X.getTargets()); - std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; - - std::cout << "L2P (forces) ... " << std::flush; - time.tic(); - // Interpolate f_i = \sum_m^L P(x_i,\bar x_m) * F_m - S.applyL2PGradient(cx, width, F, X.getTargets()); - std::cout << "took " << time.tacAndElapsed() << "s" << std::endl; - - //////////////////////////////////////////////////////////////////// - // direct computation - std::cout << "Compute interactions directly ..." << std::endl; - time.tic(); - - FReal** approx_f = new FReal* [npot]; - FReal** f = new FReal* [npot]; - for (unsigned int i=0; i<npot; ++i){ - approx_f[i] = new FReal [M * 3]; - f[i] = new FReal [M * 3]; - FBlas::setzero(M*3, f[i]); - } - - FReal** approx_p = new FReal* [npot]; - FReal** p = new FReal* [npot]; - for (unsigned int i=0; i<npot; ++i){ - approx_p[i] = new FReal [M]; - p[i] = new FReal [M]; - FBlas::setzero(M, p[i]); - } - - { // start direct computation - unsigned int counter = 0; + { // start direct computation + unsigned int counter = 0; + + for(int idxPartX = 0 ; idxPartX < X.getSrc()->getNbParticles() ; ++idxPartX){ + const FPoint x = FPoint(X.getSrc()->getPositions()[0][idxPartX], + X.getSrc()->getPositions()[1][idxPartX], + X.getSrc()->getPositions()[2][idxPartX]); + const FReal wx[nrhs] = {X.getSrc()->getPhysicalValues(0)[idxPartX], + X.getSrc()->getPhysicalValues(1)[idxPartX], + X.getSrc()->getPhysicalValues(2)[idxPartX]}; + + for(int idxPartY = 0 ; idxPartY < Y.getSrc()->getNbParticles() ; ++idxPartY){ + const FPoint y = FPoint(Y.getSrc()->getPositions()[0][idxPartY], + Y.getSrc()->getPositions()[1][idxPartY], + Y.getSrc()->getPositions()[2][idxPartY]); + const FReal wy[nrhs] = {Y.getSrc()->getPhysicalValues(0)[idxPartY], + Y.getSrc()->getPhysicalValues(1)[idxPartY], + Y.getSrc()->getPhysicalValues(2)[idxPartY]}; + + // // 1/R + // const FReal one_over_r = MatrixKernel.evaluate(x, y); + // + // // potential + // p[counter] += one_over_r * wy; + // // force + // FPoint force(y - x); + // force *= one_over_r*one_over_r*one_over_r; + // f[counter*3 + 0] += force.getX() * wx * wy; + // f[counter*3 + 1] += force.getY() * wx * wy; + // f[counter*3 + 2] += force.getZ() * wx * wy; + + FReal rij[ncmp]; + FReal rijk[ncmp][3]; + MatrixKernel.evaluateBlockAndDerivative(x,y,rij,rijk); + + // R,ij and (R,ij),k + for (unsigned int i=0; i<npot; ++i) // sum all compo + for (unsigned int j=0; j<nrhs; ++j){ + unsigned int d = MatrixKernel.getPosition(i*nrhs+j); + // potential + p[i][counter] += rij[d] * wy[j]; + // force + FReal force_k; + for (unsigned int k=0; k<3; ++k){ + // Convention in matrix kernel: R_ij(x-y), while R_ijk(y-x) + force_k = FReal(1.) * rijk[d][k]; + f[i][counter*3 + k] += force_k * wx[j] * wy[j]; + } + } - for(int idxPartX = 0 ; idxPartX < X.getSrc()->getNbParticles() ; ++idxPartX){ - const FPoint x = FPoint(X.getSrc()->getPositions()[0][idxPartX], - X.getSrc()->getPositions()[1][idxPartX], - X.getSrc()->getPositions()[2][idxPartX]); - const FReal wx[nrhs] = {X.getSrc()->getPhysicalValues(0)[idxPartX], - X.getSrc()->getPhysicalValues(1)[idxPartX], - X.getSrc()->getPhysicalValues(2)[idxPartX]}; - - for(int idxPartY = 0 ; idxPartY < Y.getSrc()->getNbParticles() ; ++idxPartY){ - const FPoint y = FPoint(Y.getSrc()->getPositions()[0][idxPartY], - Y.getSrc()->getPositions()[1][idxPartY], - Y.getSrc()->getPositions()[2][idxPartY]); - const FReal wy[nrhs] = {Y.getSrc()->getPhysicalValues(0)[idxPartY], - Y.getSrc()->getPhysicalValues(1)[idxPartY], - Y.getSrc()->getPhysicalValues(2)[idxPartY]}; - -// // 1/R -// const FReal one_over_r = MatrixKernel.evaluate(x, y); -// -// // potential -// p[counter] += one_over_r * wy; -// // force -// FPoint force(y - x); -// force *= one_over_r*one_over_r*one_over_r; -// f[counter*3 + 0] += force.getX() * wx * wy; -// f[counter*3 + 1] += force.getY() * wx * wy; -// f[counter*3 + 2] += force.getZ() * wx * wy; - - FReal rij[ncmp]; - FReal rijk[ncmp][3]; - MatrixKernel.evaluateBlockAndDerivative(x,y,rij,rijk); - - // R,ij and (R,ij),k - for (unsigned int i=0; i<npot; ++i) // sum all compo - for (unsigned int j=0; j<nrhs; ++j){ - unsigned int d = MatrixKernel.getPosition(i*nrhs+j); - // potential - p[i][counter] += rij[d] * wy[j]; - // force - FReal force_k; - for (unsigned int k=0; k<3; ++k){ - // Convention in matrix kernel: R_ij(x-y), while R_ijk(y-x) - force_k = FReal(1.) * rijk[d][k]; - f[i][counter*3 + k] += force_k * wx[j] * wy[j]; } - } + counter++; + } + } // end direct computation - } - counter++; - } - } // end direct computation + time.tac(); + std::cout << "Done in " << time.elapsed() << "sec." << std::endl; - time.tac(); - std::cout << "Done in " << time.elapsed() << "sec." << std::endl; + //////////////////////////////////////////////////////////////////// + unsigned int counter = 0; + for(int idxPartX = 0 ; idxPartX < X.getSrc()->getNbParticles() ; ++idxPartX){ + for (unsigned int i=0; i<npot; ++i){ + approx_p[i][counter] = X.getSrc()->getPotentials(i)[idxPartX]; + const FPoint force = FPoint(X.getSrc()->getForcesX(i)[idxPartX], + X.getSrc()->getForcesY(i)[idxPartX], + X.getSrc()->getForcesZ(i)[idxPartX]); + approx_f[i][counter*3 + 0] = force.getX(); + approx_f[i][counter*3 + 1] = force.getY(); + approx_f[i][counter*3 + 2] = force.getZ(); + } + counter++; + } - //////////////////////////////////////////////////////////////////// - unsigned int counter = 0; - for(int idxPartX = 0 ; idxPartX < X.getSrc()->getNbParticles() ; ++idxPartX){ - for (unsigned int i=0; i<npot; ++i){ - approx_p[i][counter] = X.getSrc()->getPotentials(i)[idxPartX]; - const FPoint force = FPoint(X.getSrc()->getForcesX(i)[idxPartX], - X.getSrc()->getForcesY(i)[idxPartX], - X.getSrc()->getForcesZ(i)[idxPartX]); - approx_f[i][counter*3 + 0] = force.getX(); - approx_f[i][counter*3 + 1] = force.getY(); - approx_f[i][counter*3 + 2] = force.getZ(); + // std::cout << "Check Potential, forceX, forceY, forceZ " << std::endl; + // for (unsigned int i=0; i<npot; ++i){ + // std::cout<< "idxLhs="<< i << std::endl; + // for(int idxPart = 0 ; idxPart < 20 ; ++idxPart){ + // std::cout << approx_p[i][idxPart] << ", "<< p[i][idxPart] << "|| "; + // std::cout << approx_f[i][idxPart] << ", "<< f[i][idxPart] << "|| "; + // std::cout << approx_f[i][idxPart+M] << ", "<< f[i][idxPart+M] << "|| "; + // std::cout << approx_f[i][idxPart+2*M] << ", "<< f[i][idxPart+2*M] << "|| "; + // std::cout << std::endl; + // } + // std::cout << std::endl; + // } + // std::cout << std::endl; + + std::cout << "\nRelative Inf/L2 errors: " << std::endl; + std::cout << " Potential:" << std::endl; + for(unsigned i = 0; i<npot;++i) { + std::cout << " " << i << ": " + << FMath::FAccurater(p[i],approx_p[i],M).getRelativeInfNorm()<<", " + << FMath::FAccurater(p[i],approx_p[i],M).getRelativeL2Norm() + << std::endl; } - counter++; - } - -// std::cout << "Check Potential, forceX, forceY, forceZ " << std::endl; -// for (unsigned int i=0; i<npot; ++i){ -// std::cout<< "idxLhs="<< i << std::endl; -// for(int idxPart = 0 ; idxPart < 20 ; ++idxPart){ -// std::cout << approx_p[i][idxPart] << ", "<< p[i][idxPart] << "|| "; -// std::cout << approx_f[i][idxPart] << ", "<< f[i][idxPart] << "|| "; -// std::cout << approx_f[i][idxPart+M] << ", "<< f[i][idxPart+M] << "|| "; -// std::cout << approx_f[i][idxPart+2*M] << ", "<< f[i][idxPart+2*M] << "|| "; -// std::cout << std::endl; -// } -// std::cout << std::endl; -// } -// std::cout << std::endl; - - std::cout << "\nRelative Inf/L2 errors: " << std::endl; - std::cout << " Potential:" << std::endl; - for(unsigned i = 0; i<npot;++i) { - std::cout << " " << i << ": " - << FMath::FAccurater(p[i],approx_p[i],M).getRelativeInfNorm()<<", " - << FMath::FAccurater(p[i],approx_p[i],M).getRelativeL2Norm() - << std::endl; - } - std::cout << std::endl; - - std::cout << " Force:" << std::endl; - for(unsigned i = 0; i<npot;++i) { - std::cout << " " << i << ": " - << FMath::FAccurater(f[i],approx_f[i],3*M).getRelativeInfNorm()<<", " - << FMath::FAccurater(f[i],approx_f[i],3*M).getRelativeL2Norm() - << std::endl; - } - std::cout << std::endl; - - // free memory - delete [] approx_p; - delete [] p; - delete [] approx_f; - delete [] f; - - - return 0; + std::cout << std::endl; + + std::cout << " Force:" << std::endl; + for(unsigned i = 0; i<npot;++i) { + std::cout << " " << i << ": " + << FMath::FAccurater(f[i],approx_f[i],3*M).getRelativeInfNorm()<<", " + << FMath::FAccurater(f[i],approx_f[i],3*M).getRelativeL2Norm() + << std::endl; + } + std::cout << std::endl; + + // free memory + delete [] approx_p; + delete [] p; + delete [] approx_f; + delete [] f; + + + return 0; } diff --git a/Tests/noDist/ChebyshevPeriodic.cpp b/Tests/noDist/ChebyshevPeriodic.cpp index bbffb5d4a7606c911da3da5c13917c5552d7bf03..a011510328c574af1c19aa5e56689060d450855e 100755 --- a/Tests/noDist/ChebyshevPeriodic.cpp +++ b/Tests/noDist/ChebyshevPeriodic.cpp @@ -42,9 +42,12 @@ #include "Core/FFmmAlgorithmPeriodic.hpp" + +#include "../../Src/Utils/FParameterNames.hpp" + template <class Output> void Print(const Output& value){ - std::cout<< "--- Output from program : " << value << "\n"; + std::cout<< "--- Output from program : " << value << "\n"; } /** @@ -57,223 +60,205 @@ void Print(const Output& value){ //! //! This code is a short example to use the Chebyshev Interpolation approach for the 1/r kernel //! -//!@Algorithm -//! <b> General arguments:</b> -//! \param -help(-h) to see the parameters available in this driver -//! \param -depth The depth of the octree -//! \param -subdepth Specifies the size of the sub octree -//! \param -t The number of threads -//! -//! \param -f name Name of the particles file with extension (.fma or .bfma). The data in file have to be in our FMA format -//! -// -void usage() { - std::cout << "Driver for Chebyshev interpolation kernel (1/r kernel)" << std::endl; - std::cout << "Options "<< std::endl - << " -help to see the parameters " << std::endl - << " -depth the depth of the octree "<< std::endl - << " -subdepth specifies the size of the sub octree " << std::endl - << " -fin name name specifies the name of the particle distribution" << std::endl - << " -fout name to write the computation in a file" << std::endl - << " -t n specifies the number of threads used in the computations" << std::endl; -} // Simply create particles and try the kernels int main(int argc, char* argv[]) { - const std::string defaultFile(/*SCALFMMDataPath+*/"../Data/test20k.fma" ); - const std::string filename = FParameters::getStr(argc,argv,"-fin", defaultFile.c_str()); - const std::string filenameOut = FParameters::getStr(argc,argv,"-fout", "resultPer.fma"); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1); - const int PeriodicDeep = FParameters::getValue(argc,argv,"-per", 3); - - if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")){ - usage() ; - exit(EXIT_SUCCESS); - } + FHelpDescribeAndExit(argc, argv, + "Driver for Chebyshev interpolation kernel (1/r kernel) with periodicity.", + FParameterDefinitions::InputFile, FParameterDefinitions::OutputFile, + FParameterDefinitions::OctreeHeight, FParameterDefinitions::OctreeSubHeight, + FParameterDefinitions::NbThreads, FParameterDefinitions::PeriodicityNbLevels); + + const std::string defaultFile(/*SCALFMMDataPath+*/"../Data/test20k.fma" ); + const std::string filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, defaultFile.c_str()); + const std::string filenameOut = FParameters::getStr(argc,argv,FParameterDefinitions::OutputFile.options, "resultPer.fma"); + 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 NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); + const int PeriodicDeep = FParameters::getValue(argc,argv,FParameterDefinitions::PeriodicityNbLevels.options, 3); + #ifdef _OPENMP - omp_set_num_threads(NbThreads); - std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; + omp_set_num_threads(NbThreads); + std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; #else - std::cout << "\n>> Sequential version.\n" << std::endl; + std::cout << "\n>> Sequential version.\n" << std::endl; #endif - // - std::cout << "Parameters "<< std::endl - << " Octree Depth "<< TreeHeight <<std::endl - << " SubOctree depth " << SubTreeHeight <<std::endl - << " Input file name: " <<filename <<std::endl - << " Thread number: " << NbThreads <<std::endl - <<std::endl; - // - // init timer - FTic time; - - // open particle file - //////////////////////////////////////////////////////////////////// - // - FFmaGenericLoader loader(filename); - FSize nbParticles = loader.getNumberOfParticles() ; - FmaRWParticle<8,8>* const particles = new FmaRWParticle<8,8>[nbParticles]; - - // - //////////////////////////////////////////////////////////////////// - // begin Chebyshev kernel - - // accuracy - const unsigned int ORDER = 7; - // typedefs - typedef FP2PParticleContainerIndexed<> ContainerClass; - typedef FSimpleLeaf< ContainerClass > LeafClass; - typedef FChebCell<ORDER> CellClass; - typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; - // - typedef FInterpMatrixKernelR MatrixKernelClass; - const MatrixKernelClass MatrixKernel; - typedef FChebSymKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; - // - typedef FFmmAlgorithmPeriodic<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; - - // init oct-tree - OctreeClass tree(TreeHeight, SubTreeHeight, loader.getBoxWidth(), loader.getCenterOfBox()); - - - { // ----------------------------------------------------- - std::cout << "Creating & Inserting " << loader.getNumberOfParticles() - << " particles ..." << std::endl; - std::cout << "\tHeight : " << TreeHeight << " \t sub-height : " << SubTreeHeight << std::endl; - time.tic(); - // - FPoint position; - // - loader.fillParticle(particles,nbParticles); - - for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - tree.insert(particles[idxPart].getPosition(), idxPart, particles[idxPart].getPhysicalValue() ); - } - - time.tac(); - std::cout << "Done " << "(@Creating and Inserting Particles = " - << time.elapsed() << " s) ." << std::endl; - } // ----------------------------------------------------- - - ///////////////////////////////////////////////////////////////////////////////////////////////// - { // ----------------------------------------------------- - std::cout << "\nChebyshev FMM (ORDER="<< ORDER << ") ... " << std::endl; - - time.tic(); - - FmmClass algo(&tree,PeriodicDeep ); - const MatrixKernelClass MatrixKernel; - KernelClass kernels(algo.extendedTreeHeight(), algo.extendedBoxWidth(), algo.extendedBoxCenter(),&MatrixKernel); - algo.setKernel(&kernels); - algo.execute(); - // - time.tac(); - std::cout << "Done " << "(@Algorithm = " << time.elapsed() << " s) ." << std::endl; - - } - // ----------------------------------------------------- - // - // Some output - // - // - FmaRWParticle<8,8>* const particlesOut = new FmaRWParticle<8,8>[nbParticles]; - - { // ----------------------------------------------------- - // - 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() ; - } - // - // Loop over all leaves - // - std::cout <<std::endl<<" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "<<std::endl; - std::cout << std::scientific; - std::cout.precision(10) ; - ///////////////////////////////////////////////////////////////////////////////////////////////// - // Compare - ///////////////////////////////////////////////////////////////////////////////////////////////// - FMath::FAccurater potentialDiff; - FMath::FAccurater fx, fy, fz; - - tree.forEachLeaf([&](LeafClass* leaf){ - const FReal*const posX = leaf->getTargets()->getPositions()[0]; - const FReal*const posY = leaf->getTargets()->getPositions()[1]; - const FReal*const posZ = leaf->getTargets()->getPositions()[2]; - 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(); - const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues(); - - const FVector<int>& indexes = leaf->getTargets()->getIndexes(); - - for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ - const int indexPartOrig = indexes[idxPart]; - // - particlesOut[indexPartOrig].setPosition(posX[idxPart],posY[idxPart],posZ[idxPart]) ; - particlesOut[indexPartOrig].setPhysicalValue(physicalValues[idxPart]) ; - particlesOut[indexPartOrig].setPotential (potentials[idxPart]) ; - particlesOut[indexPartOrig].setForces(forcesX[idxPart],forcesY[idxPart],forcesZ[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]; - } - }); - energy *= 0.5; - std::cout <<std::endl<<"Energy: "<< energy<<std::endl; - std::cout <<std::endl<<" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "<<std::endl<<std::endl; - - - // remove index - Print("Test1 - Error Relative L2 norm Potential "); - printf(" Pot L2Norm %e\n",potentialDiff.getL2Norm()); - printf(" Pot RL2Norm %e\n",potentialDiff.getRelativeL2Norm()); - printf(" Pot RMSError %e\n",potentialDiff.getRMSError()); - Print("Fx diff is = "); - printf(" Fx L2Norm %e\n",fx.getL2Norm()); - printf(" Fx RL2Norm %e\n",fx.getRelativeL2Norm()); - printf(" Fx RMSError %e\n",fx.getRMSError()); - Print("Fy diff is = "); - printf(" Fy L2Norm %e\n",fy.getL2Norm()); - printf(" Fy RL2Norm %e\n",fy.getRelativeL2Norm()); - printf(" Fy RMSError %e\n",fy.getRMSError()); - Print("Fz diff is = "); - printf(" Fz L2Norm %e\n",fz.getL2Norm()); - printf(" Fz RL2Norm %e\n",fz.getRelativeL2Norm()); - printf(" Fz RMSError %e\n",fz.getRMSError()); - FReal L2error = (fx.getRelativeL2Norm()*fx.getRelativeL2Norm() + fy.getRelativeL2Norm()*fy.getRelativeL2Norm() + fz.getRelativeL2Norm() *fz.getRelativeL2Norm() ); - printf(" Total L2 Force Error= %e\n",FMath::Sqrt(L2error)) ; - printf(" Energy Error = %.12e\n",FMath::Abs(energy-energyD)); - printf(" Energy FMM = %.12e\n",FMath::Abs(energy)); - printf(" Energy DIRECT = %.12e\n",FMath::Abs(energyD)); - - } - // ----------------------------------------------------- - if(FParameters::existParameter(argc, argv, "-fout") ){ - - std::cout << "Generate " << filenameOut <<" for output file" << std::endl; - // - std::cout << " numberofParticles: " << nbParticles <<" " << sizeof(nbParticles) <<std::endl; - std::cout << " Box size: " << loader.getBoxWidth() << " " << sizeof(loader.getBoxWidth())<<std::endl; - // - FFmaGenericWriter writer(filenameOut) ; - writer.writeHeader(loader.getCenterOfBox(), loader.getBoxWidth() , nbParticles,*particlesOut) ; - writer.writeArrayOfParticles(particlesOut, nbParticles); - - } - delete [] particlesOut; - return 0; + // + std::cout << "Parameters "<< std::endl + << " Octree Depth "<< TreeHeight <<std::endl + << " SubOctree depth " << SubTreeHeight <<std::endl + << " Input file name: " <<filename <<std::endl + << " Thread number: " << NbThreads <<std::endl + <<std::endl; + // + // init timer + FTic time; + + // open particle file + //////////////////////////////////////////////////////////////////// + // + FFmaGenericLoader loader(filename); + FSize nbParticles = loader.getNumberOfParticles() ; + FmaRWParticle<8,8>* const particles = new FmaRWParticle<8,8>[nbParticles]; + + // + //////////////////////////////////////////////////////////////////// + // begin Chebyshev kernel + + // accuracy + const unsigned int ORDER = 7; + // typedefs + typedef FP2PParticleContainerIndexed<> ContainerClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FChebCell<ORDER> CellClass; + typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; + // + typedef FInterpMatrixKernelR MatrixKernelClass; + const MatrixKernelClass MatrixKernel; + typedef FChebSymKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; + // + typedef FFmmAlgorithmPeriodic<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; + + // init oct-tree + OctreeClass tree(TreeHeight, SubTreeHeight, loader.getBoxWidth(), loader.getCenterOfBox()); + + + { // ----------------------------------------------------- + std::cout << "Creating & Inserting " << loader.getNumberOfParticles() + << " particles ..." << std::endl; + std::cout << "\tHeight : " << TreeHeight << " \t sub-height : " << SubTreeHeight << std::endl; + time.tic(); + // + FPoint position; + // + loader.fillParticle(particles,nbParticles); + + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + tree.insert(particles[idxPart].getPosition(), idxPart, particles[idxPart].getPhysicalValue() ); + } + + time.tac(); + std::cout << "Done " << "(@Creating and Inserting Particles = " + << time.elapsed() << " s) ." << std::endl; + } // ----------------------------------------------------- + + ///////////////////////////////////////////////////////////////////////////////////////////////// + { // ----------------------------------------------------- + std::cout << "\nChebyshev FMM (ORDER="<< ORDER << ") ... " << std::endl; + + time.tic(); + + FmmClass algo(&tree,PeriodicDeep ); + const MatrixKernelClass MatrixKernel; + KernelClass kernels(algo.extendedTreeHeight(), algo.extendedBoxWidth(), algo.extendedBoxCenter(),&MatrixKernel); + algo.setKernel(&kernels); + algo.execute(); + // + time.tac(); + std::cout << "Done " << "(@Algorithm = " << time.elapsed() << " s) ." << std::endl; + + } + // ----------------------------------------------------- + // + // Some output + // + // + FmaRWParticle<8,8>* const particlesOut = new FmaRWParticle<8,8>[nbParticles]; + + { // ----------------------------------------------------- + // + 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() ; + } + // + // Loop over all leaves + // + std::cout <<std::endl<<" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "<<std::endl; + std::cout << std::scientific; + std::cout.precision(10) ; + ///////////////////////////////////////////////////////////////////////////////////////////////// + // Compare + ///////////////////////////////////////////////////////////////////////////////////////////////// + FMath::FAccurater potentialDiff; + FMath::FAccurater fx, fy, fz; + + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const posX = leaf->getTargets()->getPositions()[0]; + const FReal*const posY = leaf->getTargets()->getPositions()[1]; + const FReal*const posZ = leaf->getTargets()->getPositions()[2]; + 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(); + const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues(); + + const FVector<int>& indexes = leaf->getTargets()->getIndexes(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + const int indexPartOrig = indexes[idxPart]; + // + particlesOut[indexPartOrig].setPosition(posX[idxPart],posY[idxPart],posZ[idxPart]) ; + particlesOut[indexPartOrig].setPhysicalValue(physicalValues[idxPart]) ; + particlesOut[indexPartOrig].setPotential (potentials[idxPart]) ; + particlesOut[indexPartOrig].setForces(forcesX[idxPart],forcesY[idxPart],forcesZ[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]; + } + }); + energy *= 0.5; + std::cout <<std::endl<<"Energy: "<< energy<<std::endl; + std::cout <<std::endl<<" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "<<std::endl<<std::endl; + + + // remove index + Print("Test1 - Error Relative L2 norm Potential "); + printf(" Pot L2Norm %e\n",potentialDiff.getL2Norm()); + printf(" Pot RL2Norm %e\n",potentialDiff.getRelativeL2Norm()); + printf(" Pot RMSError %e\n",potentialDiff.getRMSError()); + Print("Fx diff is = "); + printf(" Fx L2Norm %e\n",fx.getL2Norm()); + printf(" Fx RL2Norm %e\n",fx.getRelativeL2Norm()); + printf(" Fx RMSError %e\n",fx.getRMSError()); + Print("Fy diff is = "); + printf(" Fy L2Norm %e\n",fy.getL2Norm()); + printf(" Fy RL2Norm %e\n",fy.getRelativeL2Norm()); + printf(" Fy RMSError %e\n",fy.getRMSError()); + Print("Fz diff is = "); + printf(" Fz L2Norm %e\n",fz.getL2Norm()); + printf(" Fz RL2Norm %e\n",fz.getRelativeL2Norm()); + printf(" Fz RMSError %e\n",fz.getRMSError()); + FReal L2error = (fx.getRelativeL2Norm()*fx.getRelativeL2Norm() + fy.getRelativeL2Norm()*fy.getRelativeL2Norm() + fz.getRelativeL2Norm() *fz.getRelativeL2Norm() ); + printf(" Total L2 Force Error= %e\n",FMath::Sqrt(L2error)) ; + printf(" Energy Error = %.12e\n",FMath::Abs(energy-energyD)); + printf(" Energy FMM = %.12e\n",FMath::Abs(energy)); + printf(" Energy DIRECT = %.12e\n",FMath::Abs(energyD)); + + } + // ----------------------------------------------------- + if(FParameters::existParameter(argc, argv, FParameterDefinitions::OutputFile.options) ){ + + std::cout << "Generate " << filenameOut <<" for output file" << std::endl; + // + std::cout << " numberofParticles: " << nbParticles <<" " << sizeof(nbParticles) <<std::endl; + std::cout << " Box size: " << loader.getBoxWidth() << " " << sizeof(loader.getBoxWidth())<<std::endl; + // + FFmaGenericWriter writer(filenameOut) ; + writer.writeHeader(loader.getCenterOfBox(), loader.getBoxWidth() , nbParticles,*particlesOut) ; + writer.writeArrayOfParticles(particlesOut, nbParticles); + + } + delete [] particlesOut; + return 0; } diff --git a/Tests/noDist/FMMnonUnitCube.cpp b/Tests/noDist/FMMnonUnitCube.cpp index e67c8bc2ec8a770b8122e64e7481226afbba68ec..79fd636e5d136ca9a61a52b61cfd257a587a4b9a 100644 --- a/Tests/noDist/FMMnonUnitCube.cpp +++ b/Tests/noDist/FMMnonUnitCube.cpp @@ -60,6 +60,7 @@ #include "Kernels/Uniform/FUnifKernel.hpp" #endif +#include "../../Src/Utils/FParameterNames.hpp" /** * This program compute the potential and the energy in non cubic geometry @@ -81,7 +82,7 @@ void usage() { // Simply create particles and try the kernels int main(int argc, char* argv[]) { - if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")){ + if(FParameters::existParameter(argc, argv, FParameterDefinitions::OctreeHeight.options)||FParameters::existParameter(argc, argv, "-help")){ usage() ; std::cout << "Driver for testing different approximations for the 1/r kernel" << std::endl; @@ -89,10 +90,10 @@ int main(int argc, char* argv[]) } // get info from commande line - const std::string filename(FParameters::getStr(argc,argv,"-f", "../Data/UTest/unitCubeRef20kDouble.bfma")); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", omp_get_max_threads()); + const std::string filename(FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/UTest/unitCubeRef20kDouble.bfma")); + 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 NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, omp_get_max_threads()); // #ifdef _OPENMP diff --git a/Tests/noDist/compare2Files.cpp b/Tests/noDist/compare2Files.cpp index e216bcda404b00a6e520af852870edf67aa96d2f..8f6bd66b67facec09fd5609122bce9165b44cd86 100644 --- a/Tests/noDist/compare2Files.cpp +++ b/Tests/noDist/compare2Files.cpp @@ -16,7 +16,7 @@ #include "Files/FFmaGenericLoader.hpp" #include "Utils/FParameters.hpp" #include "Utils/FCompareResults.hpp" - +#include "../../Src/Utils/FParameterNames.hpp" // /// \file compare2files.cpp //! @@ -39,32 +39,20 @@ //! compare2files -file1 unitCubeXYZQ100.fma -file2 unitCubeXYZQ100 -// -// -void genDistusage() { - std::cout << "Driver to change the format of the input file" - << std::endl; - std::cout << "Options "<< std::endl - << " -help to see the parameters " << std::endl - << " -fmmfile1 name1 first file name to compare (with extension .fma (ascii) or bfma (binary) " <<std::endl - << " -fmmfile2 name2 second file name to compare (with extension .fma (ascii) or bfma (binary)" <<std::endl - << " -ewaldfile2 name2 if name2 contains the result done by the ewald method for 1/r kernel "<<std::endl - <<std::endl; -} + +static const FParameterNames LocalParameterEwald{ + {"-ewaldfile2"}, + "-ewaldfile2 name2 if name2 contains the result done by the ewald method for 1/r kernel" +}; int main(int argc, char ** argv){ - // - if(FParameters::existParameter(argc, argv, "-h")||FParameters::existParameter(argc, argv, "-help")|| (argc < 3 )){ - genDistusage() ; - exit(-1); - } - if(FParameters::existParameter(argc, argv, "-ewaldfile2")&&FParameters::existParameter(argc, argv, "-fmmfile2")){ - std::cout << "Either -file2 or -ewald have to be set"<<std::endl; - exit(-1); - } + FHelpDescribeAndExit(argc, argv, + "Driver to change the format of the input file.", + FParameterDefinitions::InputFileOne, FParameterDefinitions::InputFileTwow, + LocalParameterEwald); - const std::string filename1(FParameters::getStr(argc,argv,"-fmmfile1", "data.fma")); - const std::string filename2(FParameters::getStr(argc,argv,"-fmmfile2", "data.fma")); + const std::string filename1(FParameters::getStr(argc,argv,FParameterDefinitions::InputFileOne.options, "data.fma")); + const std::string filename2(FParameters::getStr(argc,argv,FParameterDefinitions::InputFileTwow.options, "data.fma")); FFmaGenericLoader loader1(filename1); FFmaGenericLoader loader2(filename2); @@ -88,19 +76,18 @@ int main(int argc, char ** argv){ // loader1.fillParticle(particles1,nbParticles); loader2.fillParticle(particles2,nbParticles); - if(FParameters::existParameter(argc, argv, "-ewaldfile2") ) { + if(FParameters::existParameter(argc, argv, LocalParameterEwald.options) ) { FReal volume =1.0 ; // double volume = boxsize[0] *boxsize[1]*boxsize[2] ; removeFirstMoment( "DLPOLY", nbParticles, particles2, volume) ; FPoint FirstMoment ; } // - int error = 0 ; - error = compareTwoArrays("TAG", nbParticles, particles1, particles2); + const int error = compareTwoArrays("TAG", nbParticles, particles1, particles2); // - delete particles1 ; - delete particles2 ; + delete[] particles1 ; + delete[] particles2 ; // return error; diff --git a/Tests/noDist/testACA.cpp b/Tests/noDist/testACA.cpp index 79334d75638253285d9c63d7c36d56eeabf73489..5f722e14680c5284c1e0f0276a462282d32893b0 100755 --- a/Tests/noDist/testACA.cpp +++ b/Tests/noDist/testACA.cpp @@ -34,7 +34,7 @@ #include "../../Src/Kernels/Chebyshev/FChebTensor.hpp" #include "../../Src/Kernels/Chebyshev/FChebSymM2LHandler.hpp" - +#include "../../Src/Utils/FParameterNames.hpp" /** * In this file we show how to use octree @@ -42,6 +42,8 @@ int main(int argc, char* argv[]) { + FHelpDescribeAndExit(argc, argv, "Look to the code."); + typedef FInterpMatrixKernelR MatrixKernelClass; MatrixKernelClass MatrixKernel; diff --git a/Tests/noDist/testBlockedTree.cpp b/Tests/noDist/testBlockedTree.cpp index a535599c226d8d4cbcf0c2e7026111cfd8bc47e1..8a397c44edc687ca4d9f79bdf12a7378eb1adb99 100644 --- a/Tests/noDist/testBlockedTree.cpp +++ b/Tests/noDist/testBlockedTree.cpp @@ -26,7 +26,19 @@ #include "../../Src/GroupTree/FGroupSeqAlgorithm.hpp" #include "../../Src/GroupTree/FP2PGroupParticleContainer.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + +static const FParameterNames LocalOptionBlocSize { + {"-bs"}, + "The size of the block of the blocked tree" +}; + int main(int argc, char* argv[]){ + FHelpDescribeAndExit(argc, argv, + "Test the blocked tree.", + FParameterDefinitions::OctreeHeight, FParameterDefinitions::OctreeSubHeight, + FParameterDefinitions::InputFile, LocalOptionBlocSize); + static const int P = 3; typedef FRotationCell<P> CellClass; typedef FP2PParticleContainer<> ContainerClass; @@ -36,9 +48,9 @@ int main(int argc, char* argv[]){ typedef FGroupTree< CellClass, FP2PGroupParticleContainer<>, 5, FReal> GroupOctreeClass; FTic counter; - const int NbLevels = FParameters::getValue(argc,argv,"-depth", 5); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-subdepth", 3); - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.bin.fma.double"); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.bin.fma.double"); FFmaGenericLoader loader(filename); FAssertLF(loader.isOpen()); @@ -57,7 +69,7 @@ int main(int argc, char* argv[]){ std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.tacAndElapsed() << "s)." << std::endl; - const int groupSize = FParameters::getValue(argc,argv,"-bs", 250); + const int groupSize = FParameters::getValue(argc,argv,LocalOptionBlocSize.options, 250); counter.tic(); GroupOctreeClass groupedTree2(NbLevels, groupSize, &tree); diff --git a/Tests/noDist/testChebAlgorithm.cpp b/Tests/noDist/testChebAlgorithm.cpp index 1576d148cfb9335599f19ac4671a32ed7d38d138..8d036b1a6de5b8d9c9f3f71aab467ef6cad783d4 100755 --- a/Tests/noDist/testChebAlgorithm.cpp +++ b/Tests/noDist/testChebAlgorithm.cpp @@ -42,6 +42,8 @@ #include "Core/FFmmAlgorithm.hpp" #include "Core/FFmmAlgorithmThread.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** * This program runs the FMM Algorithm with the Chebyshev kernel and compares the results with a direct computation. */ @@ -49,10 +51,15 @@ // Simply create particles and try the kernels int main(int argc, char* argv[]) { - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-depth", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-subdepth", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1); + FHelpDescribeAndExit(argc, argv, + "Test the chebyshev FMM and compare it to the direct computation for debugging purpose.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::NbThreads); + + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); + 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 NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); #ifdef _OPENMP omp_set_num_threads(NbThreads); diff --git a/Tests/noDist/testChebAlgorithmProc.cpp b/Tests/noDist/testChebAlgorithmProc.cpp index bdb6c4f18aa3286a567decca25ca209f4b38918f..76fc6c4fa978f1db0a47aea6c2809ba196c00160 100644 --- a/Tests/noDist/testChebAlgorithmProc.cpp +++ b/Tests/noDist/testChebAlgorithmProc.cpp @@ -48,6 +48,9 @@ #include "../../Src/Core/FFmmAlgorithmThreadProc.hpp" #include "../../Src/BalanceTree/FLeafBalance.hpp" + +#include "../../Src/Utils/FParameterNames.hpp" + /** * This program runs the FMM Algorithm Distributed with the Chebyshev kernel */ @@ -55,6 +58,10 @@ // Simply create particles and try the kernels int main(int argc, char* argv[]) { + FHelpDescribeAndExit(argc, argv, + "Test with MPI the chebyshev FMM and compare it to the direct computation for debugging purpose.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::NbThreads); const unsigned int ORDER = 7; const FReal epsilon = FReal(1e-7); @@ -71,10 +78,10 @@ int main(int argc, char* argv[]) FMpi app(argc,argv); - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-h", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-sh", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); + 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 NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, 1); std::cout << ">> This executable has to be used to test Proc Chebyshev Algorithm. \n"; diff --git a/Tests/noDist/testCompareKernels.cpp b/Tests/noDist/testCompareKernels.cpp index dad4f39a5e2b4ef9426cf85bd75b651df2b216d3..7c04043781573593c69ce42bab3b497528c28a89 100755 --- a/Tests/noDist/testCompareKernels.cpp +++ b/Tests/noDist/testCompareKernels.cpp @@ -51,6 +51,8 @@ #include "../../Src/Components/FSimpleLeaf.hpp" #include "../../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + /** * This program compares two different kernels, eg., the Chebyshev kernel with * the SphericalBlas kernel. @@ -60,11 +62,17 @@ // Simply create particles and try the kernels int main(int argc, char* argv[]) { + FHelpDescribeAndExit(argc, argv, + "Compare lots of kernels.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::NbThreads, + FParameterDefinitions::SHDevelopment); + // get info from commandline - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); - const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-h", 5); - const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-sh", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", omp_get_max_threads()); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma"); + 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 NbThreads = FParameters::getValue(argc, argv, FParameterDefinitions::NbThreads.options, omp_get_max_threads()); omp_set_num_threads(NbThreads); @@ -198,7 +206,7 @@ int main(int argc, char* argv[]) { // begin FFmaBlas kernel // accuracy - const int DevP = FParameters::getValue(argc, argv, "-p", 11); + const int DevP = FParameters::getValue(argc, argv, FParameterDefinitions::SHDevelopment.options, 11); // typedefs typedef FSphericalCell CellClass; diff --git a/Tests/noDist/testFmmAdaptiveAlgorithm.cpp b/Tests/noDist/testFmmAdaptiveAlgorithm.cpp index 4c2022634e8aeb3a882e5241a2d4e51383bd8c7b..230353103cc14a4cda0a6289d9e33f30d51f9769 100644 --- a/Tests/noDist/testFmmAdaptiveAlgorithm.cpp +++ b/Tests/noDist/testFmmAdaptiveAlgorithm.cpp @@ -45,6 +45,8 @@ #include "../../Src/Adaptive/FAdaptiveKernelWrapper.hpp" #include "../../Src/Adaptive/FAbstractAdaptiveKernel.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + template< class CellClass, class ContainerClass> class FAdaptiveTestKernel : public FTestKernels<CellClass, ContainerClass>, public FAbstractAdaptiveKernel<CellClass, ContainerClass> { public: @@ -115,6 +117,11 @@ public: // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Test the adaptive FMM.", + FParameterDefinitions::NbParticles, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight,); + typedef FTestCell CellClass; typedef FTestParticleContainer ContainerClass; @@ -131,14 +138,14 @@ 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,"-h", 7); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 7); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); FTic counter; ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// - FRandomLoader loader(FParameters::getValue(argc,argv,"-nb", 2000000), 1, FPoint(0.5,0.5,0.5), 1); + FRandomLoader loader(FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 2000000), 1, FPoint(0.5,0.5,0.5), 1); OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); ////////////////////////////////////////////////////////////////////////////////// @@ -179,7 +186,7 @@ int main(int argc, char ** argv){ long long int*const particlesAttributes = leaf->getTargets()->getDataDown(); for(int idxPart = 0 ; idxPart < leaf->getTargets()->getNbParticles() ; ++idxPart){ if(particlesAttributes[idxPart] != (loader.getNumberOfParticles()-1)){ - printf("Incorrect %lld instead of %d\n", particlesAttributes[idxPart], (loader.getNumberOfParticles()-1)); + std::cout << "Incorrect " << particlesAttributes[idxPart] << " instead of " << (loader.getNumberOfParticles()-1) << "\n"; } } }); diff --git a/Tests/noDist/testFmmAdaptiveStats.cpp b/Tests/noDist/testFmmAdaptiveStats.cpp index 0c27c98544133b4a43afe938ce515f98458bfbeb..46484a5d4153dcdcaa16db6f593ffca16a260cbd 100644 --- a/Tests/noDist/testFmmAdaptiveStats.cpp +++ b/Tests/noDist/testFmmAdaptiveStats.cpp @@ -46,6 +46,8 @@ #include "../../Src/Adaptive/FAdaptiveKernelWrapper.hpp" #include "../../Src/Adaptive/FAbstractAdaptiveKernel.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + template< class CellClass, class ContainerClass> class FAdaptiveStatsKernel : public FAbstractKernels<CellClass, ContainerClass>, public FAbstractAdaptiveKernel<CellClass, ContainerClass> { const int nbLevels; @@ -249,6 +251,11 @@ public: // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Test the adaptive FMM and print information about the real computation which is done.", + FParameterDefinitions::NbParticles, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight); + typedef FBasicCell CellClass; typedef FBasicParticleContainer<0> ContainerClass; @@ -263,15 +270,15 @@ 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,"-h", 7); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 7); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3); const int ParticlesThresh = FParameters::getValue(argc,argv,"-thresh", 10); FTic counter; ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// - FRandomLoader loader(FParameters::getValue(argc,argv,"-nb", 2000000), 1, FPoint(0.5,0.5,0.5), 1); + FRandomLoader loader(FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 2000000), 1, FPoint(0.5,0.5,0.5), 1); OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); ////////////////////////////////////////////////////////////////////////////////// diff --git a/Tests/noDist/testNewCompareKernels.cpp b/Tests/noDist/testNewCompareKernels.cpp index 7dca8230e4d2646bdb73d8def5dbe4e8e3d8fc69..e28dd51ec7fe141e640e3c672ba01fb4f01134f0 100644 --- a/Tests/noDist/testNewCompareKernels.cpp +++ b/Tests/noDist/testNewCompareKernels.cpp @@ -75,6 +75,8 @@ #include "Kernels/Uniform/FUnifKernel.hpp" #endif +#include "../../Src/Utils/FParameterNames.hpp" + /** * This program compares two different kernels, eg., the Chebyshev kernel with diff --git a/Tests/noDist/testP2PAvx.cpp b/Tests/noDist/testP2PAvx.cpp index 0074693b306707fee3f50cb0ec470b32317ebff6..9ba274b9aa0c92d4bf69ce2583378ca3cb3d1f15 100644 --- a/Tests/noDist/testP2PAvx.cpp +++ b/Tests/noDist/testP2PAvx.cpp @@ -35,6 +35,7 @@ #include "Components/FSimpleLeaf.hpp" #include "Containers/FOctree.hpp" +#include "../../Src/Utils/FParameterNames.hpp" // /// \file DirectComputation.cpp @@ -48,32 +49,24 @@ //! \param -fin name: file name to convert (with extension .fma (ascii) or bfma (binary). //! Only our FMA (.bma, .bfma) is allowed " //! \param -fout filenameOUT output file with extension (default output.bfma) -//! \param -verbose : print index x y z Q V fx fy fz //! // Simply create particles and try the kernels int main(int argc, char ** argv){ // ///////////////////////What we do///////////////////////////// - if( FParameters::existParameter(argc, argv, "-help" )){ - std::cout << ">> This executable has to be used to compute interaction either for periodic or non periodic system.\n"; - std::cout << ">> Example -fin filenameIN.{fma or bfma) -fout filenameOUT{fma or bfma) \n"; - std::cout << ">> Default input file : ../Data/unitCubeXYZQ20k.fma\n"; - std::cout << " Options " << std::endl; - std::cout << " -verbose : print index x y z Q V fx fy fz " << std::endl; - std::cout << " -fin filename. Extension specifies if the file is binary or not. " << std::endl; - std::cout << " Only our FMA (.bma, .bfma) is allowed " << std::endl; - std::cout << " -fout filenameOUT output file with extension (default output.bfma)" << std::endl; - exit(-1); - - } + FHelpDescribeAndExit(argc, argv, + "This executable has to be used to compute interaction either for periodic or non periodic system.\n" + "Example -fin filenameIN.{fma or bfma)\n" + "Default input file : ../Data/unitCubeXYZQ20k.fma\n" + "For the input file, the extension specifies if the file is binary or not.\n", + FParameterDefinitions::InputFile); ////////////////////////////////////////////////////////////// const std::string defaultFile(/*SCALFMMDataPath+*/"../Data/unitCubeXYZQ20k.fma"); - const std::string filenameIn(FParameters::getStr(argc,argv,"-fin", defaultFile.c_str())); - const std::string filenameOut(FParameters::getStr(argc,argv,"-fout", "output.bfma")); - // + const std::string filenameIn(FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, defaultFile.c_str())); + FTic counter; // ----------------------------------------------------- diff --git a/Tests/noDist/testSphericalBlasBlockProc.cpp b/Tests/noDist/testSphericalBlasBlockProc.cpp index 6949d219a7e7737c444c88519ad4ba1f64e3a51c..ea3b1d1e67518b6c032d135c8c87594c13dc6da4 100644 --- a/Tests/noDist/testSphericalBlasBlockProc.cpp +++ b/Tests/noDist/testSphericalBlasBlockProc.cpp @@ -44,9 +44,17 @@ #include "../../Src/BalanceTree/FLeafBalance.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + // Simply create particles and try the kernels int main(int argc, char ** argv){ + FHelpDescribeAndExit(argc, argv, + "Test Spherical HArmonic kernel with blas.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::SHDevelopment, + FParameterDefinitions::NbThreads); + typedef FSphericalCell CellClass; typedef FP2PParticleContainer<> ContainerClass; @@ -64,15 +72,15 @@ int main(int argc, char ** argv){ 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); + const int DevP = FParameters::getValue(argc,argv,FParameterDefinitions::SHDevelopment.options, 8); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 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); + const char* const filename = FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, defaultFilename); + const int nbThreads = FParameters::getValue(argc,argv,FParameterDefinitions::NbThreads.options,8); omp_set_num_threads(nbThreads); std::cout << "Opening : " << filename << "\n"; diff --git a/Tests/noDist/testSphericalBlasProc.cpp b/Tests/noDist/testSphericalBlasProc.cpp index 1c3f396408497c9c12f7a7ec8afd06d1fb4622ac..0ca4a5e2300376b20d6f8b274cd2cfb167700b68 100644 --- a/Tests/noDist/testSphericalBlasProc.cpp +++ b/Tests/noDist/testSphericalBlasProc.cpp @@ -44,165 +44,173 @@ #include "../../Src/BalanceTree/FLeafBalance.hpp" +#include "../../Src/Utils/FParameterNames.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; - } - }; + FHelpDescribeAndExit(argc, argv, + "Test Spherical HArmonic kernel with blas and using MPI.", + FParameterDefinitions::InputFile, FParameterDefinitions::OctreeHeight, + FParameterDefinitions::OctreeSubHeight, FParameterDefinitions::SHDevelopment, + FParameterDefinitions::NbThreads); + + 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,FParameterDefinitions::SHDevelopment.options, 8); + const int NbLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 5); + const int SizeSubLevels = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 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,FParameterDefinitions::InputFile.options, defaultFilename); + const int nbThreads = FParameters::getValue(argc,argv,FParameterDefinitions::NbThreads.options,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; + } - TestParticle* particles = new TestParticle[loader.getNumberOfParticles()]; - memset(particles, 0, sizeof(TestParticle) * loader.getNumberOfParticles()); + CellClass::Init(DevP); - 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); + OctreeClass tree(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); - } + // ----------------------------------------------------- - delete[] particles; + std::cout << "Creating & Inserting " << loader.getNumberOfParticles() << " particles ..." << std::endl; + std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; + counter.tic(); - 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); + 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; + counter.tac(); + std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; - // ----------------------------------------------------- - std::cout << "Create kernel..." << std::endl; + // ----------------------------------------------------- + std::cout << "Create kernel..." << std::endl; - KernelClass kernels(DevP, NbLevels,loader.getBoxWidth(), loader.getCenterOfBox()); + KernelClass kernels(DevP, NbLevels,loader.getBoxWidth(), loader.getCenterOfBox()); - std::cout << "Done " << " in " << counter.elapsed() << "s)." << std::endl; + std::cout << "Done " << " in " << counter.elapsed() << "s)." << std::endl; - // ----------------------------------------------------- + // ----------------------------------------------------- - std::cout << "Working on particles ..." << std::endl; + std::cout << "Working on particles ..." << std::endl; - FmmClass algo(app.global(),&tree,&kernels); + FmmClass algo(app.global(),&tree,&kernels); - counter.tic(); - algo.execute(); - counter.tac(); + counter.tic(); + algo.execute(); + counter.tac(); - std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl; + std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl; - { // get sum forces&potential + { // get sum forces&potential - FReal potential = 0; - FReal fx = 0.0, fy = 0.0, fz = 0.0; + 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(); + 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]; - } - }); + 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; + 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); + 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; + 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; + return 0; } diff --git a/Tests/noDist/testSphericalDebug.cpp b/Tests/noDist/testSphericalDebug.cpp index 8e014b0d551e6efce6b73227c3f07c24205bdbbb..a9c6fb18b8b486c1210ac83f808c046453010ca2 100755 --- a/Tests/noDist/testSphericalDebug.cpp +++ b/Tests/noDist/testSphericalDebug.cpp @@ -36,6 +36,8 @@ #include "../Src/Core/FFmmAlgorithmThread.hpp" #include "../Src/Core/FFmmAlgorithm.hpp" +#include "../../Src/Utils/FParameterNames.hpp" + #include "../UTests/FUTester.hpp" /* diff --git a/Tests/testParameterNames.cpp b/Tests/testParameterNames.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fca3f3552a7451c046233db834153ce7bddf5026 --- /dev/null +++ b/Tests/testParameterNames.cpp @@ -0,0 +1,14 @@ +#include "../Src/Utils/FParameterNames.hpp" + +#include <iostream> + +int main(int argc, char** argv){ + + //FHelpAndExit(argc, argv, FParameterDefinitions::NbParticles, FParameterDefinitions::OctreeSubHeight ); + FHelpDescribeAndExit(argc, argv, "It is made to test the parameters common to all binaries.", + FParameterDefinitions::NbParticles, FParameterDefinitions::OctreeSubHeight); + + std::cout << "Pass -help to the executable to know how to use it\n"; + + return 0; +}