From d70d77e129584725ddc7a01af8f18a0c4d97bbcf Mon Sep 17 00:00:00 2001 From: Olivier Coulaud <Olivier.Coulaud@inria.fr> Date: Mon, 12 Mar 2018 17:18:42 +0100 Subject: [PATCH] Remove duplicated code for Adaptive Interpolation FMM in Example --- .../ChebyshevInterpolationAdaptiveFMM.cpp | 265 +-------------- Examples/LagrangeInterpolationAdaptiveFMM.cpp | 304 +---------------- Examples/sharedMemoryInterpolationFMM.hpp | 2 +- .../sharedMemorynterpolationAdaptiveFMM.hpp | 317 ++++++++++++++++++ 4 files changed, 348 insertions(+), 540 deletions(-) create mode 100644 Examples/sharedMemorynterpolationAdaptiveFMM.hpp diff --git a/Examples/ChebyshevInterpolationAdaptiveFMM.cpp b/Examples/ChebyshevInterpolationAdaptiveFMM.cpp index daef0cb51..87a4621d7 100644 --- a/Examples/ChebyshevInterpolationAdaptiveFMM.cpp +++ b/Examples/ChebyshevInterpolationAdaptiveFMM.cpp @@ -21,267 +21,32 @@ // @SCALFMM_PRIVATE // ================ -/** \brief Uniform FMM example +/** \brief Chebyshev adaptive FMM example * * \file - * \authors B. Bramas, O. Coulaud + * \authors O. Coulaud * - * This program runs the FMM Algorithm with the interpolation kernel based on + * This program runs the Adaptive FMM Algorithm with the interpolation kernel based on * uniform (grid points) interpolation (1/r kernel). It then compares the * results with a direct computation. */ - -#include <iostream> -#include <iomanip> - -#include <cstdio> -#include <cstdlib> -#include <memory> #include <string> - -#include <omp.h> - -#include "ScalFmmConfig.h" - -#include "Files/FFmaGenericLoader.hpp" - -#include "Kernels/Interpolation/FInterpMatrixKernel.hpp" #include "Kernels/Chebyshev/FChebCell.hpp" #include "Adaptive/FAdaptChebKernel.hpp" - -#include "Components/FSimpleLeaf.hpp" -#include "Kernels/P2P/FP2PParticleContainerIndexed.hpp" - -#include "Utils/FParameters.hpp" -#include "Utils/FParameterNames.hpp" - -#include "Adaptive/FAdaptiveSequential.hpp" -#include "Adaptive/FAdaptiveTask.hpp" -#include "Adaptive/FTree.hpp" - -// Types definition - -// accuracy -typedef double FReal; -const unsigned int ORDER = 7; - -using ContainerClass = FP2PParticleContainerIndexed<FReal>; -using CellClass = FChebCell<FReal, ORDER>; -using OctreeClass = FTree<ContainerClass,CellClass>; -using LeafClass = typename OctreeClass::node_t; -// -using MatrixKernelClass = FInterpMatrixKernelR<FReal>; -using KernelClass = FAdaptChebKernel<FReal, CellClass, ContainerClass, MatrixKernelClass, ORDER>; // -using FmmClass = FAdaptiveTask<OctreeClass, KernelClass>; -using FmmClassSeq = FAdaptiveSequential<OctreeClass, KernelClass>; - -namespace FPD = FParameterDefinitions; -namespace FParameterDefinitions { - FParameterNames Density = { - {"--max-density", "-d"}, "Maximun particle count per leaf." - }; - FParameterNames PrintParticles = { - {"--print-particles"}, "Print particles in tree." - }; - FParameterNames UseSequential = { - {"--seq"}, "Use sequential algorithm" - }; -} - -int main(int argc, char* argv[]) { - FHelpDescribeAndExit( - argc, argv, - "Driver for Lagrange interpolation kernel (1/r kernel).", - FPD::InputFile, - FPD::OutputFile, - FPD::NbThreads, - FPD::Density, - FPD::UseSequential, - ); - - - const std::string defaultFile(SCALFMMDataPath+"unitCubeXYZQ100.bfma" ); - - const std::string filename = - FParameters::getStr(argc, argv, FPD::InputFile.options, defaultFile.c_str()); - - const unsigned int NbThreads = - FParameters::getValue(argc, argv, FPD::NbThreads.options, omp_get_max_threads()); - omp_set_num_threads(NbThreads); +template<typename FReal, int ORDER> +using FInterpolationCell = FChebCell<FReal, ORDER>; - const unsigned int maxDensity = - FParameters::getValue(argc, argv, FPD::Density.options, 1U); - - { - std::string indent(" "); - auto w = std::setw(18); - std::cout << "Parameters" << std::endl << std::left - << indent << w << "Input file : " << filename << std::endl - << indent << w << "Thread number: " << NbThreads << std::endl - << std::endl; - } - // - // init timer - FTic time; - - // open particle file - FFmaGenericLoader<FReal> loader(filename); - - const MatrixKernelClass MatrixKernel; - - // init oct-tree - OctreeClass tree({loader.getBoxWidth(), loader.getCenterOfBox()}); - tree.leaf_max_particle_count(maxDensity); - if(FParameters::existParameter(argc, argv, FPD::PrintParticles.options)) { - tree.print_particles = true; - } - - { // ----------------------------------------------------- - std::cout << "Creating & Inserting " << loader.getNumberOfParticles() - << " particles ..." << std::endl; - time.tic(); - // - FPoint<FReal> position; - FReal physicalValue = 0.0; - // - for(FSize idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - // Read particle per particle from file - loader.fillParticle(&position,&physicalValue); - // put particle in octree - tree.insert(position, idxPart, physicalValue); - } - - time.tac(); - std::cout << "Done " << "(@Creating and Inserting Particles = " - << time.elapsed() << " s)." << std::endl; - std::cout << "Tree height: " << tree.height() << std::endl; - - std::fstream("tree.txt", std::ios::out) << tree; - } // ----------------------------------------------------- - - { // ----------------------------------------------------- - std::cout << "\nChebyshev FMM (ORDER="<< ORDER << ") ... " << std::endl; - time.tic(); - // - // - - KernelClass kernel( - static_cast<int>(tree.height()), - loader.getBoxWidth(), - loader.getCenterOfBox(), - &MatrixKernel); - if(FParameters::existParameter(argc, argv, FPD::UseSequential.options)) { - FmmClassSeq algo(&tree, &kernel); - algo.execute(); // FMM algorithm call - } else { -#ifndef __INTEL_COMPILER - FmmClass algo(&tree, &kernel); - algo.execute(); // FMM algorithm call -#else - std::cerr << " No FMM algorithm with Intel compiler" <<std::endl; -#endif - } - - // - // - time.tac(); - std::cout << "Done " << "(@Algorithm = " << time.elapsed() << " s) ." << std::endl; - } - // ----------------------------------------------------- - // - // Some output - // - // - { // ----------------------------------------------------- - FSize 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 FSize nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); - const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues(); - - const FVector<FSize>& indexes = leaf->getTargets()->getIndexes(); - - for(FSize idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ - const FSize indexPartOrig = indexes[idxPart]; - if ((indexPartOrig == N1) || (indexPartOrig == N2) || (indexPartOrig == N3) ) { - std::cout << "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] ; - } - }); - std::cout <<std::endl<<"Energy: "<< energy<<std::endl; - std::cout <<std::endl<<" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "<<std::endl<<std::endl; - - } - // ----------------------------------------------------- - if(FParameters::existParameter(argc, argv, FPD::OutputFile.options)){ - std::string name(FParameters::getStr(argc,argv,FPD::OutputFile.options, "output.fma")); - FFmaGenericWriter<FReal> writer(name) ; - // - FSize NbPoints = loader.getNumberOfParticles(); - FReal * particles ; - particles = new FReal[8*NbPoints] ; - memset(particles,0,8*NbPoints*sizeof(FReal)); - FSize j = 0 ; - tree.forEachLeaf([&](LeafClass* leaf){ - // - // Input - 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 physicalValues = leaf->getTargets()->getPhysicalValues(); - const FVector<FSize>& indexes = leaf->getTargets()->getIndexes(); - // - // Computed data - 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 FSize nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); - for(FSize idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ - j = 8*indexes[idxPart]; - particles[j] = posX[idxPart] ; - particles[j+1] = posY[idxPart] ; - particles[j+2] = posZ[idxPart] ; - particles[j+3] = physicalValues[idxPart] ; - particles[j+4] = potentials[idxPart] ; - particles[j+5] = forcesX[idxPart] ; - particles[j+6] = forcesY[idxPart] ; - particles[j+7] = forcesZ[idxPart] ; - } - }); - - writer.writeHeader( loader.getCenterOfBox(), loader.getBoxWidth() , NbPoints, sizeof(FReal), 8) ; - writer.writeArrayOfReal(particles, 8 , NbPoints); - - delete[] particles; - // -// std::string name1( "output.fma"); -// - // FFmaGenericWriter<FReal> writer1(name1) ; - // writer1.writeDistributionOfParticlesFromOctree(&tree,NbPoints) ; - } +template<typename FReal, typename GroupCellClass, + typename GroupContainerClass, + typename MatrixKernelClass, int ORDER> +using FInterpolationAdaptiveKernel = FAdaptChebKernel<FReal, + GroupCellClass, + GroupContainerClass, + MatrixKernelClass, + ORDER> ; +const std::string interpolationType("Chebyshev interpolation"); - return 0; -} +#include "sharedMemorynterpolationAdaptiveFMM.hpp" diff --git a/Examples/LagrangeInterpolationAdaptiveFMM.cpp b/Examples/LagrangeInterpolationAdaptiveFMM.cpp index 6973959f7..7ab1b8098 100644 --- a/Examples/LagrangeInterpolationAdaptiveFMM.cpp +++ b/Examples/LagrangeInterpolationAdaptiveFMM.cpp @@ -1,19 +1,3 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Berenger Bramas -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== - // ==== CMAKE ===== // @FUSE_FFT // @FUSE_BLAS @@ -21,290 +5,32 @@ // @SCALFMM_PRIVATE // ================ -/** \brief Uniform FMM example +/** \brief equispaced point (Uniform or Lagrange) Adaptive FMM example * * \file - * \authors B. Bramas, O. Coulaud + * \authors O. Coulaud * - * This program runs the FMM Algorithm with the interpolation kernel based on + * This program runs the Adaptive FMM Algorithm with the interpolation kernel based on * uniform (grid points) interpolation (1/r kernel). It then compares the * results with a direct computation. */ - -#include <iostream> -#include <iomanip> - -#include <cstdio> -#include <cstdlib> -#include <memory> #include <string> - -#include <omp.h> - -#include "ScalFmmConfig.h" - -#include "Files/FFmaGenericLoader.hpp" - -#include "Kernels/Interpolation/FInterpMatrixKernel.hpp" #include "Kernels/Uniform/FUnifCell.hpp" #include "Adaptive/FAdaptUnifKernel.hpp" - -#include "Components/FSimpleLeaf.hpp" -#include "Kernels/P2P/FP2PParticleContainerIndexed.hpp" - -#include "Utils/FParameters.hpp" -#include "Utils/FParameterNames.hpp" - -#include "Adaptive/FAdaptiveSequential.hpp" -#include "Adaptive/FAdaptiveTask.hpp" - -#ifdef SCALFMM_USE_STARPU -#include "Adaptive/FAdaptiveStarPU.hpp" -#endif - -#include "Adaptive/FTree.hpp" - - -// Types definition - -// accuracy -typedef double FReal; -const unsigned int ORDER = 7; - -using ContainerClass = FP2PParticleContainerIndexed<FReal>; -using CellClass = FUnifCell<FReal, ORDER>; -using OctreeClass = FTree<ContainerClass,CellClass>; -using LeafClass = typename OctreeClass::node_t; -// -using MatrixKernelClass = FInterpMatrixKernelR<FReal>; -using KernelClass = FAdaptUnifKernel<FReal, CellClass, ContainerClass, MatrixKernelClass, ORDER>; // -using FmmClass = FAdaptiveTask<OctreeClass, KernelClass>; -using FmmClassSeq = FAdaptiveSequential<OctreeClass, KernelClass>; - -#ifdef SCALFMM_USE_STARPU -using FmmClassStarPU = FAdaptiveStarPU<OctreeClass, KernelClass>; -#endif - -namespace FPD = FParameterDefinitions; -namespace FParameterDefinitions { - FParameterNames Density = { - {"--max-density", "-d"}, "Maximun particle count per leaf." - }; - FParameterNames PrintParticles = { - {"--print-particles"}, "Print particles in tree." - }; - FParameterNames UseSequential = { - {"--seq"}, "Use sequential algorithm" - }; - FParameterNames UseStarPU = { - {"--starpu"}, "Use StarPU algorithm" - }; -} - -int main(int argc, char* argv[]) { - FHelpDescribeAndExit( - argc, argv, - "Driver for Lagrange interpolation kernel (1/r kernel).", - FPD::InputFile, - FPD::OutputFile, - FPD::NbThreads, - FPD::Density, - FPD::UseSequential, - FPD::UseStarPU, - ); - - - const std::string defaultFile(SCALFMMDataPath+"unitCubeXYZQ100.bfma" ); - - const std::string filename = - FParameters::getStr(argc, argv, FPD::InputFile.options, defaultFile.c_str()); +template<typename FReal, int ORDER> +using FInterpolationCell = FUnifCell<FReal, ORDER>; - const unsigned int NbThreads = - FParameters::getValue(argc, argv, FPD::NbThreads.options, omp_get_max_threads()); - omp_set_num_threads(NbThreads); - - const unsigned int maxDensity = - FParameters::getValue(argc, argv, FPD::Density.options, 1U); - - { - std::string indent(" "); - auto w = std::setw(18); - std::cout << "Parameters" << std::endl << std::left - << indent << w << "Input file : " << filename << std::endl - << indent << w << "Thread number: " << NbThreads << std::endl - << std::endl; - } - // - // init timer - FTic time; - - // open particle file - FFmaGenericLoader<FReal> loader(filename); - - const MatrixKernelClass MatrixKernel; - - // init oct-tree - OctreeClass tree({loader.getBoxWidth(), loader.getCenterOfBox()}); - tree.leaf_max_particle_count(maxDensity); - if(FParameters::existParameter(argc, argv, FPD::PrintParticles.options)) { - tree.print_particles = true; - } - - { // ----------------------------------------------------- - std::cout << "Creating & Inserting " << loader.getNumberOfParticles() - << " particles ..." << std::endl; - time.tic(); - // - FPoint<FReal> position; - FReal physicalValue = 0.0; - // - for(FSize idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - // Read particle per particle from file - loader.fillParticle(&position,&physicalValue); - // put particle in octree - tree.insert(position, idxPart, physicalValue); - } - - time.tac(); - std::cout << "Done " << "(@Creating and Inserting Particles = " - << time.elapsed() << " s)." << std::endl; - std::cout << "Tree height: " << tree.height() << std::endl; - - std::fstream("tree.txt", std::ios::out) << tree; - } // ----------------------------------------------------- - - { // ----------------------------------------------------- - std::cout << "\nLagrange FMM (ORDER="<< ORDER << ") ... " << std::endl; - time.tic(); - // - // - - KernelClass kernel( - static_cast<int>(tree.height()), - loader.getBoxWidth(), - loader.getCenterOfBox(), - &MatrixKernel); - - - unsigned int operations = FFmmNearAndFarFields; - - if(FParameters::existParameter(argc, argv, FPD::UseSequential.options)) { - FmmClassSeq algo(&tree, &kernel); - algo.execute(operations); // FMM algorithm call -#ifdef SCALFMM_USE_STARPU - } else if(FParameters::existParameter(argc, argv, FPD::UseStarPU.options)) { - FmmClassStarPU algo(&tree, &kernel); - algo.execute(operations); // FMM algorithm call -#endif - } else { -#ifndef __INTEL_COMPILER - FmmClass algo(&tree, &kernel); - algo.execute(operations); // FMM algorithm call -#endif - } - - - // - // - time.tac(); - std::cout << "Done " << "(@Algorithm = " << time.elapsed() << " s) ." << std::endl; - } - // ----------------------------------------------------- - // - // Some output - // - // - { // ----------------------------------------------------- - FSize 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 FSize nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); - const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues(); - - const FVector<FSize>& indexes = leaf->getTargets()->getIndexes(); - - for(FSize idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ - const FSize indexPartOrig = indexes[idxPart]; - if ((indexPartOrig == N1) || (indexPartOrig == N2) || (indexPartOrig == N3) ) { - std::cout << "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] ; - } - }); - std::cout <<std::endl<<"Energy: "<< energy<<std::endl; - std::cout <<std::endl<<" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "<<std::endl<<std::endl; - - } - // ----------------------------------------------------- - if(FParameters::existParameter(argc, argv, FPD::OutputFile.options)){ - std::string name(FParameters::getStr(argc,argv,FPD::OutputFile.options, "output.fma")); - FFmaGenericWriter<FReal> writer(name) ; - // - FSize NbPoints = loader.getNumberOfParticles(); - FReal * particles ; - particles = new FReal[8*NbPoints] ; - memset(particles,0,8*NbPoints*sizeof(FReal)); - FSize j = 0 ; - tree.forEachLeaf([&](LeafClass* leaf){ - // - // Input - 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 physicalValues = leaf->getTargets()->getPhysicalValues(); - const FVector<FSize>& indexes = leaf->getTargets()->getIndexes(); - // - // Computed data - 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 FSize nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); - for(FSize idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ - j = 8*indexes[idxPart]; - particles[j] = posX[idxPart] ; - particles[j+1] = posY[idxPart] ; - particles[j+2] = posZ[idxPart] ; - particles[j+3] = physicalValues[idxPart] ; - particles[j+4] = potentials[idxPart] ; - particles[j+5] = forcesX[idxPart] ; - particles[j+6] = forcesY[idxPart] ; - particles[j+7] = forcesZ[idxPart] ; - } - }); - - writer.writeHeader( loader.getCenterOfBox(), loader.getBoxWidth() , NbPoints, sizeof(FReal), 8) ; - writer.writeArrayOfReal(particles, 8 , NbPoints); - - delete[] particles; - - // -// std::string name1( "output.fma"); -// - // FFmaGenericWriter<FReal> writer1(name1) ; - // writer1.writeDistributionOfParticlesFromOctree(&tree,NbPoints) ; - } +template<typename FReal, typename GroupCellClass, + typename GroupContainerClass, + typename MatrixKernelClass, int ORDER> +using FInterpolationAdaptiveKernel = FAdaptUnifKernel<FReal, + GroupCellClass, + GroupContainerClass, + MatrixKernelClass, + ORDER> ; +const std::string interpolationType("Lagrange equispaced points interpolation"); - return 0; -} +#include "sharedMemorynterpolationAdaptiveFMM.hpp" diff --git a/Examples/sharedMemoryInterpolationFMM.hpp b/Examples/sharedMemoryInterpolationFMM.hpp index 7df1cfcb9..ec975d149 100644 --- a/Examples/sharedMemoryInterpolationFMM.hpp +++ b/Examples/sharedMemoryInterpolationFMM.hpp @@ -44,7 +44,7 @@ // // // Order of the Interpolation approximation -static const unsigned ORDER = 6 ; +static constexpr unsigned ORDER = 6 ; using FReal = double; // 1/r kernel // diff --git a/Examples/sharedMemorynterpolationAdaptiveFMM.hpp b/Examples/sharedMemorynterpolationAdaptiveFMM.hpp new file mode 100644 index 000000000..849b3ee7f --- /dev/null +++ b/Examples/sharedMemorynterpolationAdaptiveFMM.hpp @@ -0,0 +1,317 @@ +// =================================================================================== +// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Berenger Bramas +// olivier.coulaud@inria.fr, berenger.bramas@inria.fr +// This software is a computer program whose purpose is to compute the FMM. +// +// This software is governed by the CeCILL-C and LGPL licenses and +// abiding by the rules of distribution of free software. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public and CeCILL-C Licenses for more details. +// "http://www.cecill.info". +// "http://www.gnu.org/licenses". +// =================================================================================== + +// ==== CMAKE ===== +// @FUSE_FFT +// @FUSE_BLAS +// ==== Git ===== +// @SCALFMM_PRIVATE +// ================ + +/** \brief Uniform FMM example + * + * \file + * \authors B. Bramas, O. Coulaud + * + * This program runs the FMM Algorithm with the interpolation kernel based on + * uniform (grid points) interpolation (1/r kernel). It then compares the + * results with a direct computation. + */ + + +#include <iostream> +#include <iomanip> + +#include <cstdio> +#include <cstdlib> +#include <memory> +#include <string> + +#ifdef _OPENMP +#include <omp.h> +#endif +#include "ScalFmmConfig.h" + +#include "Files/FFmaGenericLoader.hpp" + +#include "Kernels/Interpolation/FInterpMatrixKernel.hpp" + +#include "Components/FSimpleLeaf.hpp" +#include "Kernels/P2P/FP2PParticleContainerIndexed.hpp" + +#include "Utils/FParameters.hpp" +#include "Utils/FParameterNames.hpp" + +#ifdef _OPENMP +#include "Adaptive/FAdaptiveTask.hpp" +#endif +#include "Adaptive/FAdaptiveSequential.hpp" + +#ifdef SCALFMM_USE_STARPU +#include "Adaptive/FAdaptiveStarPU.hpp" +#endif + +#include "Adaptive/FTree.hpp" + + +// Types definition + +// accuracy +typedef double FReal; +constexpr unsigned int ORDER = 7; + +// +// Specification +using MatrixKernelClass = FInterpMatrixKernelR<FReal>; +// +// +/// definition of the common tree structure +// +using ContainerClass = FP2PParticleContainerIndexed<FReal>; +using CellClass = FInterpolationCell<FReal, ORDER>; +using OctreeClass = FTree<ContainerClass,CellClass>; +using LeafClass = typename OctreeClass::node_t; + +using KernelClass = FInterpolationAdaptiveKernel<FReal,CellClass,ContainerClass,MatrixKernelClass,ORDER> ; + +using FmmClass = FAdaptiveTask<OctreeClass, KernelClass>; +using FmmClassSeq = FAdaptiveSequential<OctreeClass, KernelClass>; + +#ifdef SCALFMM_USE_STARPU +using FmmClassStarPU = FAdaptiveStarPU<OctreeClass, KernelClass>; +#endif + +namespace FPD = FParameterDefinitions; +namespace FParameterDefinitions { + FParameterNames Density = { + {"--max-density", "-d"}, "Maximun particle count per leaf." + }; + FParameterNames PrintParticles = { + {"--print-particles"}, "Print particles in tree." + }; + FParameterNames UseSequential = { + {"--seq"}, "Use sequential algorithm" + }; + FParameterNames UseStarPU = { + {"--starpu"}, "Use StarPU algorithm" + }; +} + +int main(int argc, char* argv[]) { + FHelpDescribeAndExit( + argc, argv, + "Driver for Lagrange interpolation kernel (1/r kernel).", + FPD::InputFile, + FPD::OutputFile, + FPD::NbThreads, + FPD::Density, + FPD::UseSequential, + FPD::UseStarPU, + ); + + + const std::string defaultFile(SCALFMMDataPath+"unitCubeXYZQ100.bfma" ); + + const std::string filename = + FParameters::getStr(argc, argv, FPD::InputFile.options, defaultFile.c_str()); + + const unsigned int NbThreads = + FParameters::getValue(argc, argv, FPD::NbThreads.options, omp_get_max_threads()); + omp_set_num_threads(NbThreads); + + const unsigned int maxDensity = + FParameters::getValue(argc, argv, FPD::Density.options, 1U); + + { + std::string indent(" "); + auto w = std::setw(18); + std::cout << "Parameters" << std::endl << std::left + << indent << w << "Input file : " << filename << std::endl + << indent << w << "Thread number: " << NbThreads << std::endl + << std::endl; + } + // + // init timer + FTic time; + + // open particle file + FFmaGenericLoader<FReal> loader(filename); + + const MatrixKernelClass MatrixKernel; + + // init oct-tree + OctreeClass tree({loader.getBoxWidth(), loader.getCenterOfBox()}); + tree.leaf_max_particle_count(maxDensity); + if(FParameters::existParameter(argc, argv, FPD::PrintParticles.options)) { + tree.print_particles = true; + } + + { // ----------------------------------------------------- + std::cout << "Creating & Inserting " << loader.getNumberOfParticles() + << " particles ..." << std::endl; + time.tic(); + // + FPoint<FReal> position; + FReal physicalValue = 0.0; + // + for(FSize idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + // Read particle per particle from file + loader.fillParticle(&position,&physicalValue); + // put particle in octree + tree.insert(position, idxPart, physicalValue); + } + + time.tac(); + std::cout << "Done " << "(@Creating and Inserting Particles = " + << time.elapsed() << " s)." << std::endl; + std::cout << "Tree height: " << tree.height() << std::endl; + + std::fstream("tree.txt", std::ios::out) << tree; + } // ----------------------------------------------------- + + { // ----------------------------------------------------- + std::cout << "\n" << interpolationType << " FMM (ORDER= "<< ORDER << ") ... " << std::endl; + time.tic(); + // + // + + KernelClass kernel( + static_cast<int>(tree.height()), + loader.getBoxWidth(), + loader.getCenterOfBox(), + &MatrixKernel); + + + unsigned int operations = FFmmNearAndFarFields; + + if(FParameters::existParameter(argc, argv, FPD::UseSequential.options)) { + FmmClassSeq algo(&tree, &kernel); + algo.execute(operations); // FMM algorithm call +#ifdef SCALFMM_USE_STARPU + } else if(FParameters::existParameter(argc, argv, FPD::UseStarPU.options)) { + FmmClassStarPU algo(&tree, &kernel); + algo.execute(operations); // FMM algorithm call +#endif + } else { +#ifndef __INTEL_COMPILER + FmmClass algo(&tree, &kernel); + algo.execute(operations); // FMM algorithm call +#endif + } + + + // + // + time.tac(); + std::cout << "Done " << "(@Algorithm = " << time.elapsed() << " s) ." << std::endl; + } + // ----------------------------------------------------- + // + // Some output + // + // + { // ----------------------------------------------------- + FSize 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 FSize nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues(); + + const FVector<FSize>& indexes = leaf->getTargets()->getIndexes(); + + for(FSize idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + const FSize indexPartOrig = indexes[idxPart]; + if ((indexPartOrig == N1) || (indexPartOrig == N2) || (indexPartOrig == N3) ) { + std::cout << "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] ; + } + }); + std::cout <<std::endl<<"Energy: "<< energy<<std::endl; + std::cout <<std::endl<<" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& "<<std::endl<<std::endl; + + } + // ----------------------------------------------------- + if(FParameters::existParameter(argc, argv, FPD::OutputFile.options)){ + std::string name(FParameters::getStr(argc,argv,FPD::OutputFile.options, "output.fma")); + FFmaGenericWriter<FReal> writer(name) ; + // + FSize NbPoints = loader.getNumberOfParticles(); + FReal * particles ; + particles = new FReal[8*NbPoints] ; + memset(particles,0,8*NbPoints*sizeof(FReal)); + FSize j = 0 ; + tree.forEachLeaf([&](LeafClass* leaf){ + // + // Input + 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 physicalValues = leaf->getTargets()->getPhysicalValues(); + const FVector<FSize>& indexes = leaf->getTargets()->getIndexes(); + // + // Computed data + 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 FSize nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + for(FSize idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + j = 8*indexes[idxPart]; + particles[j] = posX[idxPart] ; + particles[j+1] = posY[idxPart] ; + particles[j+2] = posZ[idxPart] ; + particles[j+3] = physicalValues[idxPart] ; + particles[j+4] = potentials[idxPart] ; + particles[j+5] = forcesX[idxPart] ; + particles[j+6] = forcesY[idxPart] ; + particles[j+7] = forcesZ[idxPart] ; + } + }); + + writer.writeHeader( loader.getCenterOfBox(), loader.getBoxWidth() , NbPoints, sizeof(FReal), 8) ; + writer.writeArrayOfReal(particles, 8 , NbPoints); + + delete[] particles; + + // +// std::string name1( "output.fma"); +// + // FFmaGenericWriter<FReal> writer1(name1) ; + // writer1.writeDistributionOfParticlesFromOctree(&tree,NbPoints) ; + } + + + return 0; +} -- GitLab