From 00fcfecfdf61268f007c3d9d6dbddae795d91ef5 Mon Sep 17 00:00:00 2001 From: berenger-bramas <berenger-bramas@2616d619-271b-44dc-8df4-d4a8f33a7222> Date: Tue, 26 Apr 2011 11:18:59 +0000 Subject: [PATCH] Change directory Sources into Src Change Macro FUSE into SCALFMM_USE git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/scalfmm/scalfmm/trunk@60 2616d619-271b-44dc-8df4-d4a8f33a7222 --- CMakeLists.txt | 39 +- Sources/CMakeLists.txt | 25 - Sources/Components/FAbstractCell.hpp | 73 - Sources/Components/FAbstractKernels.hpp | 91 - Sources/Components/FAbstractLeaf.hpp | 50 - Sources/Components/FAbstractParticle.hpp | 41 - Sources/Components/FBasicCell.hpp | 29 - Sources/Components/FBasicKernels.hpp | 69 - Sources/Components/FBasicParticle.hpp | 28 - Sources/Components/FFmaParticle.hpp | 26 - Sources/Components/FSimpleLeaf.hpp | 54 - Sources/Components/FTestCell.hpp | 41 - Sources/Components/FTestKernels.hpp | 173 -- Sources/Components/FTestParticle.hpp | 39 - Sources/Components/FTypedLeaf.hpp | 58 - Sources/Containers/FList.hpp | 282 --- Sources/Containers/FOctree.hpp | 788 -------- Sources/Containers/FSubOctree.hpp | 452 ----- Sources/Containers/FTreeCoordinate.hpp | 188 -- Sources/Core/FFmmAlgorithm.hpp | 237 --- Sources/Core/FFmmAlgorithmThread.hpp | 352 ---- Sources/Core/FFmmAlgorithmThreadProc.hpp | 572 ------ Sources/Core/FFmmAlgorithmThreadTsm.hpp | 367 ---- Sources/Core/FFmmAlgorithmThreadUs.hpp | 318 ---- Sources/Core/FFmmAlgorithmTsm.hpp | 288 --- Sources/Extenssions/FExtendCellType.hpp | 69 - Sources/Extenssions/FExtendForces.hpp | 61 - Sources/Extenssions/FExtendMortonIndex.hpp | 52 - Sources/Extenssions/FExtendParticleType.hpp | 84 - Sources/Extenssions/FExtendPhysicalValue.hpp | 52 - Sources/Extenssions/FExtendPosition.hpp | 60 - Sources/Extenssions/FExtendPotential.hpp | 52 - Sources/Files/FAbstractLoader.hpp | 64 - Sources/Files/FBasicLoader.hpp | 119 -- Sources/Files/FFmaLoader.hpp | 123 -- Sources/Files/FFmaScanfLoader.hpp | 137 -- Sources/Files/FFmaTsmLoader.hpp | 126 -- Sources/Fmb/FExtendFmbCell.hpp | 72 - Sources/Fmb/FFmbKernels.hpp | 1488 --------------- Sources/Fmb/FFmbKernelsBlas.hpp | 1448 --------------- Sources/Fmb/FFmbKernelsBlockBlas.hpp | 1703 ------------------ Sources/ScalFmmConfig.h.cmake | 6 - Sources/Utils/F3DPosition.hpp | 231 --- Sources/Utils/FAbstractApplication.hpp | 212 --- Sources/Utils/FAssertable.cpp | 16 - Sources/Utils/FAssertable.hpp | 77 - Sources/Utils/FBlas.hpp | 73 - Sources/Utils/FComplexe.hpp | 153 -- Sources/Utils/FConvert.hpp | 37 - Sources/Utils/FDebug.cpp | 12 - Sources/Utils/FDebug.hpp | 187 -- Sources/Utils/FGlobal.hpp | 57 - Sources/Utils/FMath.hpp | 103 -- Sources/Utils/FMpiApplication.hpp | 101 -- Sources/Utils/FSingleApplication.hpp | 88 - Sources/Utils/FTic.hpp | 74 - Sources/Utils/FTrace.cpp | 12 - Sources/Utils/FTrace.hpp | 231 --- Tests/testApplication.cpp | 12 +- Tests/testAssert.cpp | 6 +- Tests/testDebug.cpp | 6 +- Tests/testFmbAlgorithm.cpp | 32 +- Tests/testFmbBlasAlgorithm.cpp | 38 +- Tests/testFmbTsmAlgorithm.cpp | 32 +- Tests/testFmbTsmNoTsm.cpp | 38 +- Tests/testFmmAlgorithm.cpp | 26 +- Tests/testFmmAlgorithmProc.cpp | 77 +- Tests/testFmmAlgorithmTsm.cpp | 26 +- Tests/testLoader.cpp | 20 +- Tests/testLoaderCreate.cpp | 2 +- Tests/testLoaderFMA.cpp | 20 +- Tests/testLoaderFMACreate.cpp | 2 +- Tests/testLoaderFMACreateSphere.cpp | 2 +- Tests/testLoaderFMATsm.cpp | 22 +- Tests/testLoaderFMATsmCreate.cpp | 2 +- Tests/testOctree.cpp | 18 +- Tests/testOctreeIter.cpp | 18 +- Tests/testOctreePrintMorton.cpp | 6 +- Tests/testTic.cpp | 2 +- UTests/utestConvert.cpp | 10 +- UTests/utestList.cpp | 208 +-- UTests/utestMorton.cpp | 142 +- 82 files changed, 420 insertions(+), 12407 deletions(-) delete mode 100644 Sources/CMakeLists.txt delete mode 100644 Sources/Components/FAbstractCell.hpp delete mode 100644 Sources/Components/FAbstractKernels.hpp delete mode 100644 Sources/Components/FAbstractLeaf.hpp delete mode 100644 Sources/Components/FAbstractParticle.hpp delete mode 100644 Sources/Components/FBasicCell.hpp delete mode 100644 Sources/Components/FBasicKernels.hpp delete mode 100644 Sources/Components/FBasicParticle.hpp delete mode 100644 Sources/Components/FFmaParticle.hpp delete mode 100644 Sources/Components/FSimpleLeaf.hpp delete mode 100644 Sources/Components/FTestCell.hpp delete mode 100644 Sources/Components/FTestKernels.hpp delete mode 100644 Sources/Components/FTestParticle.hpp delete mode 100644 Sources/Components/FTypedLeaf.hpp delete mode 100644 Sources/Containers/FList.hpp delete mode 100644 Sources/Containers/FOctree.hpp delete mode 100644 Sources/Containers/FSubOctree.hpp delete mode 100644 Sources/Containers/FTreeCoordinate.hpp delete mode 100644 Sources/Core/FFmmAlgorithm.hpp delete mode 100644 Sources/Core/FFmmAlgorithmThread.hpp delete mode 100644 Sources/Core/FFmmAlgorithmThreadProc.hpp delete mode 100644 Sources/Core/FFmmAlgorithmThreadTsm.hpp delete mode 100644 Sources/Core/FFmmAlgorithmThreadUs.hpp delete mode 100644 Sources/Core/FFmmAlgorithmTsm.hpp delete mode 100644 Sources/Extenssions/FExtendCellType.hpp delete mode 100644 Sources/Extenssions/FExtendForces.hpp delete mode 100644 Sources/Extenssions/FExtendMortonIndex.hpp delete mode 100644 Sources/Extenssions/FExtendParticleType.hpp delete mode 100644 Sources/Extenssions/FExtendPhysicalValue.hpp delete mode 100644 Sources/Extenssions/FExtendPosition.hpp delete mode 100644 Sources/Extenssions/FExtendPotential.hpp delete mode 100644 Sources/Files/FAbstractLoader.hpp delete mode 100644 Sources/Files/FBasicLoader.hpp delete mode 100644 Sources/Files/FFmaLoader.hpp delete mode 100644 Sources/Files/FFmaScanfLoader.hpp delete mode 100644 Sources/Files/FFmaTsmLoader.hpp delete mode 100644 Sources/Fmb/FExtendFmbCell.hpp delete mode 100644 Sources/Fmb/FFmbKernels.hpp delete mode 100644 Sources/Fmb/FFmbKernelsBlas.hpp delete mode 100644 Sources/Fmb/FFmbKernelsBlockBlas.hpp delete mode 100644 Sources/ScalFmmConfig.h.cmake delete mode 100644 Sources/Utils/F3DPosition.hpp delete mode 100644 Sources/Utils/FAbstractApplication.hpp delete mode 100644 Sources/Utils/FAssertable.cpp delete mode 100644 Sources/Utils/FAssertable.hpp delete mode 100644 Sources/Utils/FBlas.hpp delete mode 100644 Sources/Utils/FComplexe.hpp delete mode 100644 Sources/Utils/FConvert.hpp delete mode 100644 Sources/Utils/FDebug.cpp delete mode 100644 Sources/Utils/FDebug.hpp delete mode 100644 Sources/Utils/FGlobal.hpp delete mode 100644 Sources/Utils/FMath.hpp delete mode 100644 Sources/Utils/FMpiApplication.hpp delete mode 100644 Sources/Utils/FSingleApplication.hpp delete mode 100644 Sources/Utils/FTic.hpp delete mode 100644 Sources/Utils/FTrace.cpp delete mode 100644 Sources/Utils/FTrace.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 31d2df4f1..a62d0d0e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,5 @@ cmake_minimum_required (VERSION 2.6) -# Project Infos -project(scalfmm CXX) - # check if compiling into source directories STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" insource) if(insource) @@ -10,36 +7,38 @@ if(insource) endif(insource) # Options -OPTION( FUSE_CBLAS "Set to ON to build ScaFMM with BLAS" ON ) -OPTION( FUSE_MPI "Set to ON to build ScaFMM with MPI" OFF ) +OPTION( SCALFMM_USE_CBLAS "Set to ON to build ScaFMM with BLAS" ON ) +OPTION( SCALFMM_USE_MPI "Set to ON to build ScaFMM with MPI" OFF ) OPTION( BUILD_TESTS "Set to ON to build fonctionnalities Tests" ON ) OPTION( BUILD_UTESTS "Set to ON to build UTests" ON ) +# MPI option +if( SCALFMM_USE_MPI ) + SET(CMAKE_CXX_COMPILER mpicxx) +endif() + +# Project Infos +project(scalfmm CXX) + # Blas option -if( FUSE_CBLAS ) - OPTION( FUSE_MKL_AS_BLAS "Set to ON to use MKL CBLAS" OFF ) - if( FUSE_MKL_AS_BLAS ) +if( SCALFMM_USE_CBLAS ) + OPTION( SCALFMM_USE_MKL_AS_BLAS "Set to ON to use MKL CBLAS" OFF ) + if( SCALFMM_USE_MKL_AS_BLAS ) SET(CBLAS_LIBRARIES "-L$ENV{MKLROOT}/lib -lmkl_intel_lp64 -lmkl_sequential -lmkl_core") - else( FUSE_MKL_AS_BLAS ) + else() FIND_PACKAGE(BLAS) SET(CBLAS_LIBRARIES "-lcblas") - endif( FUSE_MKL_AS_BLAS ) -endif( FUSE_CBLAS ) - -# MPI option -if( FUSE_MPI ) - SET(CMAKE_CXX_COMPILER mpicxx) -endif(FUSE_MPI) - + endif() +endif() # Compile option ADD_DEFINITIONS(-O2 -Wall -Wshadow -Wpointer-arith -Wcast-qual) -CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/Sources/ScalFmmConfig.h.cmake - ${CMAKE_BINARY_DIR}/Sources/ScalFmmConfig.h ) +CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/Src/ScalFmmConfig.h.cmake + ${CMAKE_BINARY_DIR}/Src/ScalFmmConfig.h ) # Build - lib -add_subdirectory(Sources) +add_subdirectory(Src) # Build - Tests MESSAGE( STATUS "BUILD_TESTS = ${BUILD_TESTS}" ) diff --git a/Sources/CMakeLists.txt b/Sources/CMakeLists.txt deleted file mode 100644 index c258069d8..000000000 --- a/Sources/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -cmake_minimum_required(VERSION 2.6) - -# Configuration du projet -project(Lib_scalfmm) -set(LIBRARY_OUTPUT_PATH ../lib/${CMAKE_BUILD_TYPE}) - -# Searching all cpp file -file( - GLOB_RECURSE - source_lib_files - ./*.cpp -) - -# Adding cpp files to project -add_library( - scalfmm - STATIC - ${source_lib_files} -) - -# Adding the entire project dir as an include dir -INCLUDE_DIRECTORIES( - ${CMAKE_BINARY_DIR}/Sources -) - diff --git a/Sources/Components/FAbstractCell.hpp b/Sources/Components/FAbstractCell.hpp deleted file mode 100644 index 9825d325d..000000000 --- a/Sources/Components/FAbstractCell.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef FABSTRACTCELL_HPP -#define FABSTRACTCELL_HPP -// /!\ Please, you must read the license at the bottom of this page - - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FAbstractCell -* @brief -* Please read the license -* -* This class define the method that every cell class -* has to implement. -* -* In fact FOctree & FFmmAlgorithm need this function to be implemented. -* But you cannot use this interface with the extension (as an example : -* because the compiler will faill to know if getMortonIndex is coming -* from this interface or from the extension) -* -* @warning Inherite from this class when implement a specific cell type -*/ -class FAbstractCell{ -public: - /** Default destructor */ - virtual ~FAbstractCell(){ - } - - /** - * Must be implemented by each user Cell class - * @return the position of the current cell - */ - virtual MortonIndex getMortonIndex() const = 0; - - - /** - * Must be implemented by each user Cell class - * @param inIndex the position of the current cell - */ - virtual void setMortonIndex(const MortonIndex inIndex) = 0; - - /** - * Must be implemented by each user Cell class - * @param inPosition the position of the current cell - */ - virtual void setPosition(const F3DPosition& inPosition) = 0; - - /** Because the system can run in Tsm mode - * a cell has to express if it has sources - * @return true if there are sources particles inside - */ - virtual bool hasSourcesChild() const = 0; - - /** Because the system can run in Tsm mode - * a cell has to express if it has targets - * @return true if there are targets particles inside - */ - virtual bool hasTargetsChild() const = 0; - - /** - * This function make the cell containing sources - */ - virtual void setSourcesChildTrue() = 0; - - /** - * This function make the cell containing targets - */ - virtual void setTargetsChildTrue() = 0; -}; - - -#endif //FABSTRACTCELL_HPP - -// [--LICENSE--] diff --git a/Sources/Components/FAbstractKernels.hpp b/Sources/Components/FAbstractKernels.hpp deleted file mode 100644 index 8d4eb78fc..000000000 --- a/Sources/Components/FAbstractKernels.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef FABSTRACTKERNELS_HPP -#define FABSTRACTKERNELS_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FGlobal.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FAbstractKernels -* @brief -* Please read the license -* -* If you want to create you own kernels you have to inherit from this class. -*/ -template< class ParticleClass, class CellClass, int TreeHeight> -class FAbstractKernels{ -public: - /** Default destructor */ - virtual ~FAbstractKernels(){ - } - - /** - * Init the Kernels - * This function is called just before to start the computation - */ - virtual void init(){} - - /** - * P2M - * particles to multipole - * @param pole the multipole to fill using the particles - * @param particles the particles from the same spacial boxe - */ - virtual void P2M(CellClass* const pole, const FList<ParticleClass*>* const particles) = 0; - - /** - * M2M - * Multipole to multipole - * @param pole the father (the boxe that contains other ones) - * @param child the boxe to take values from - * @param the current computation level - * the child array has a size of 8 elements (address if exists or 0 otherwise). - * You must test if a pointer is 0 to know if an element exists inside this array - */ - virtual void M2M(CellClass* const FRestrict pole, const CellClass*const FRestrict *const FRestrict child, const int inLevel) = 0; - - /** - * M2L - * Multipole to local - * @param local the element to fill using distant neighbors - * @param distantNeighbors is an array containing fathers's direct neighbors's child - direct neigbors - * @param size the number of neighbors - * @param inLevel the current level of the computation - */ - virtual void M2L(CellClass* const FRestrict local, const CellClass*const FRestrict *const FRestrict distantNeighbors, const int size, const int inLevel) = 0; - - /** - * L2L - * Local to local - * @param the father to take value from - * @param the child to downward values (child may have already been impacted by M2L) - * @param level the current level of computation - * the child array has a size of 8 elements (address if exists or 0 otherwise). - * You must test if a pointer is 0 to know if an element exists inside this array - */ - virtual void L2L(const CellClass* const FRestrict local, CellClass* FRestrict * const FRestrict child, const int inLevel) = 0; - - /** - * L2P - * Local to particles - * @param local the leaf element (smaller boxe local element) - * @param particles the list of particles inside this boxe - */ - virtual void L2P(const CellClass* const local, FList<ParticleClass*>* const particles) = 0; - - /** - * P2P - * Particles to particles - * @param targets current boxe targets particles - * @param sources current boxe sources particles - * @param directNeighborsParticles the particles from direct neighbors (this is an array of list) - * @param size the number of direct neighbors (the size of the array directNeighborsParticles) - */ - virtual void P2P(FList<ParticleClass*>* const FRestrict targets, const FList<ParticleClass*>* const FRestrict sources, - FList<ParticleClass*>*const FRestrict *const FRestrict directNeighborsParticles, const int size) = 0; -}; - - -#endif //FABSTRACTKERNELS_HPP - -// [--LICENSE--] diff --git a/Sources/Components/FAbstractLeaf.hpp b/Sources/Components/FAbstractLeaf.hpp deleted file mode 100644 index 4e13ec5f6..000000000 --- a/Sources/Components/FAbstractLeaf.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef FABSTRACTLEAF_HPP -#define FABSTRACTLEAF_HPP -// /!\ Please, you must read the license at the bottom of this page - - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FAbstractLeaf -* @brief -* Please read the license -* This class is used to enable the use of typed particles -* (source XOR target) or simple system (source AND target) -*/ -template< class ParticleClass > -class FAbstractLeaf { -public: - /** Default destructor */ - virtual ~FAbstractLeaf(){ - } - - /** - * To add a new particle in the leaf - * @param particle the new particle - * Depending on the system to use the class that inherit - * this interface can sort the particle as they like. - */ - virtual void push(ParticleClass* const particle) = 0; - - /** - * To get all the sources in a leaf - * @return a pointer to the list of particles that are sources - * Depending on the system to use the class that inherit - * this interface can sort the particle as they like. - */ - virtual FList<ParticleClass*>* getSources() = 0; - - /** - * To get all the target in a leaf - * @return a pointer to the list of particles that are targets - * Depending on the system to use the class that inherit - * this interface can sort the particle as they like. - */ - virtual FList<ParticleClass*>* getTargets() = 0; - -}; - - -#endif //FABSTRACTLEAF_HPP - -// [--LICENSE--] diff --git a/Sources/Components/FAbstractParticle.hpp b/Sources/Components/FAbstractParticle.hpp deleted file mode 100644 index b6794bc8c..000000000 --- a/Sources/Components/FAbstractParticle.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef FABSTRACTPARTICLE_HPP -#define FABSTRACTPARTICLE_HPP -// /!\ Please, you must read the license at the bottom of this page - -/* forward declaration to avoid include */ -class F3DPosition; - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FAbstractBody -* @brief -* Please read the license -* -* This class define the method that every particle class -* has to implement. -* -* In fact FOctree & FFmmAlgorithm need this function to be implemented. -* But you cannot use this interface with the extension (as an example : -* because the compiler will faill to know if getPosition is coming -* from this interface or from the extension) -* -* -* @warning Inherite from this class when implement a specific particle type -*/ -class FAbstractParticle{ -public: - /** Default destructor */ - virtual ~FAbstractParticle(){ - } - - /** - * Must be implemented by each user Particle class - * @return the position of the current cell - */ - virtual F3DPosition getPosition() const = 0; -}; - - -#endif //FABSTRACTPARTICLE_HPP - -// [--LICENSE--] diff --git a/Sources/Components/FBasicCell.hpp b/Sources/Components/FBasicCell.hpp deleted file mode 100644 index f3a88a8fd..000000000 --- a/Sources/Components/FBasicCell.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef FBASICCELL_HPP -#define FBASICCELL_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Extenssions/FExtendPosition.hpp" -#include "../Extenssions/FExtendMortonIndex.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FBasicCell -* Please read the license -* -* This class defines a basic cell used for examples. It extends -* the mininum, only what is needed by FOctree and FFmmAlgorithm -* to make the things working. -* By using this extension it will implement the FAbstractCell without -* inheriting from it. -*/ -class FBasicCell : public FExtendPosition, public FExtendMortonIndex { -public: - /** Default destructor */ - virtual ~FBasicCell(){ - } -}; - - -#endif //FBASICCELL_HPP - -// [--LICENSE--] diff --git a/Sources/Components/FBasicKernels.hpp b/Sources/Components/FBasicKernels.hpp deleted file mode 100644 index ec00c5d34..000000000 --- a/Sources/Components/FBasicKernels.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef FBASICKERNELS_HPP -#define FBASICKERNELS_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "FAbstractKernels.hpp" - -#include "../Utils/FTrace.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class AbstractKernels -* @brief -* Please read the license -* -* This kernels simply shows the details of the information -* it receives (in debug) -*/ -template< class ParticleClass, class CellClass, int TreeHeight> -class FBasicKernels : public FAbstractKernels<ParticleClass,CellClass,TreeHeight> { -public: - /** Default destructor */ - virtual ~FBasicKernels(){ - } - - /** When init the kernel */ - virtual void init(){} - - /** Print the number of particles */ - virtual void P2M(CellClass* const , const FList<ParticleClass*>* const ) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - /** Print the morton index */ - virtual void M2M(CellClass* const FRestrict , const CellClass*const FRestrict *const FRestrict , const int ) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - /** Print the morton index */ - virtual void M2L(CellClass* const FRestrict , const CellClass*const FRestrict *const FRestrict , const int , const int ) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - /** Print the morton index */ - virtual void L2L(const CellClass* const FRestrict , CellClass* FRestrict *const FRestrict , const int ) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - /** Print the number of particles */ - virtual void L2P(const CellClass* const , FList<ParticleClass*>* const ){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - /** Print the number of particles */ - virtual void P2P(FList<ParticleClass*>* const FRestrict , const FList<ParticleClass*>* const FRestrict , - FList<ParticleClass*>* FRestrict const* FRestrict , const int ) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } -}; - - -#endif //FBASICKERNELS_HPP - -// [--LICENSE--] diff --git a/Sources/Components/FBasicParticle.hpp b/Sources/Components/FBasicParticle.hpp deleted file mode 100644 index 3c78fe136..000000000 --- a/Sources/Components/FBasicParticle.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef FBASICPARTICLE_HPP -#define FBASICPARTICLE_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Extenssions/FExtendPosition.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FBasicParticle -* Please read the license -* -* This class defines a basic particle used for examples. It extends -* the mininum, only what is needed by FOctree and FFmmAlgorithm -* to make the things working. -* By using this extension it will implement the FAbstractParticle without -* inheriting from it. -*/ -class FBasicParticle : public FExtendPosition{ -public: - /** Default destructor */ - virtual ~FBasicParticle(){ - } -}; - - -#endif //FBASICPARTICLE_HPP - -// [--LICENSE--] diff --git a/Sources/Components/FFmaParticle.hpp b/Sources/Components/FFmaParticle.hpp deleted file mode 100644 index 71e98cef4..000000000 --- a/Sources/Components/FFmaParticle.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef FFmaPARTICLE_HPP -#define FFmaPARTICLE_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "FBasicParticle.hpp" -#include "../Extenssions/FExtendPhysicalValue.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmaParticle -* Please read the license -* -* This class defines a particle for FMA loader. -* As defined in FFmaLoader it needs {FBasicParticle,FExtendPhysicalValue} -*/ -class FFmaParticle : public FBasicParticle, public FExtendPhysicalValue { -public: - /** Default destructor */ - virtual ~FFmaParticle(){ - } -}; - - -#endif //FFmaPARTICLE_HPP - -// [--LICENSE--] diff --git a/Sources/Components/FSimpleLeaf.hpp b/Sources/Components/FSimpleLeaf.hpp deleted file mode 100644 index f18bafbb2..000000000 --- a/Sources/Components/FSimpleLeaf.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef FSIMPLELEAF_HPP -#define FSIMPLELEAF_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Containers/FList.hpp" -#include "FAbstractLeaf.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FSimpleLeaf -* @brief -* Please read the license -* This class is used as a leaf in simple system (source AND target) -* here there is only one list that store all particles. -*/ -template< class ParticleClass > -class FSimpleLeaf : public FAbstractLeaf<ParticleClass> { - FList<ParticleClass*> particles; - -public: - /** Default destructor */ - virtual ~FSimpleLeaf(){ - } - - /** - * To add a new particle in the leaf - * @param particle the new particle - */ - void push(ParticleClass* const particle){ - this->particles.pushFront(particle); - } - - /** - * To get all the sources in a leaf - * @return a pointer to the list of particles that are sources - */ - FList<ParticleClass*>* getSources() { - return &this->particles; - } - - /** - * To get all the target in a leaf - * @return a pointer to the list of particles that are targets - */ - FList<ParticleClass*>* getTargets() { - return &this->particles; - } - -}; - - -#endif //FSIMPLELEAF_HPP - -// [--LICENSE--] diff --git a/Sources/Components/FTestCell.hpp b/Sources/Components/FTestCell.hpp deleted file mode 100644 index 3ad03419b..000000000 --- a/Sources/Components/FTestCell.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef FTESTCELL_HPP -#define FTESTCELL_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "FBasicCell.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FBasicCell -* Please read the license -* -* This class is used in the FTestKernels, please -* look at this class to know whit it is. -*/ -class FTestCell : public FBasicCell { - // To store data during upward and downward pass - long dataUp, dataDown; -public: - FTestCell(): dataUp(0) , dataDown(0){ - } - /** Default destructor */ - virtual ~FTestCell(){ - } - long getDataUp() const { - return this->dataUp; - } - void setDataUp(const long inData){ - this->dataUp = inData; - } - long getDataDown() const { - return this->dataDown; - } - void setDataDown(const long inData){ - this->dataDown = inData; - } -}; - - -#endif //FTESTCELL_HPP - -// [--LICENSE--] diff --git a/Sources/Components/FTestKernels.hpp b/Sources/Components/FTestKernels.hpp deleted file mode 100644 index 12b39cec3..000000000 --- a/Sources/Components/FTestKernels.hpp +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef FTESTKERNELS_HPP -#define FTESTKERNELS_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include <iostream> - -#include "FAbstractKernels.hpp" -#include "../Containers/FList.hpp" -#include "../Containers/FOctree.hpp" - -#include "../Utils/FTrace.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class AbstractKernels -* @brief -* Please read the license -* -* This kernels is a virtual kernels to validate that the fmm algorithm is -* correctly done on particles. -* It used FTestCell and FTestParticle -*/ -template< class ParticleClass, class CellClass, int TreeHeight> -class FTestKernels : public FAbstractKernels<ParticleClass,CellClass,TreeHeight> { -public: - /** Default destructor */ - virtual ~FTestKernels(){ - } - - // Before upward - void P2M(CellClass* const pole, const FList<ParticleClass*>* const particles) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - // the pole represents all particles under - pole->setDataUp(particles->getSize()); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - // During upward - void M2M(CellClass* const FRestrict pole, const CellClass *const FRestrict *const FRestrict child, const int ) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - // A parent represents the sum of the child - for(int idx = 0 ; idx < 8 ; ++idx){ - if(child[idx]){ - pole->setDataUp(pole->getDataUp() + child[idx]->getDataUp()); - } - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - // Before Downward - void M2L(CellClass* const FRestrict pole, const CellClass*const FRestrict *const distantNeighbors, const int size, const int ) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - // The pole is impacted by what represent other poles - for(int idx = 0 ; idx < size ; ++idx){ - pole->setDataDown(pole->getDataDown() + distantNeighbors[idx]->getDataUp()); - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - // During Downward - void L2L(const CellClass*const FRestrict local, CellClass* FRestrict *const FRestrict child, const int) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - // Each child is impacted by the father - for(int idx = 0 ; idx < 8 ; ++idx){ - if(child[idx]){ - child[idx]->setDataDown(local->getDataDown() + child[idx]->getDataDown()); - } - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - // After Downward - void L2P(const CellClass* const local, FList<ParticleClass*>*const particles){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - // The particles is impacted by the parent cell - typename FList<ParticleClass*>::BasicIterator iter(*particles); - while( iter.isValide() ){ - iter.value()->setDataDown(iter.value()->getDataDown() + local->getDataDown()); - iter.progress(); - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - // After Downward - void P2P(FList<ParticleClass*>* const FRestrict targets, const FList<ParticleClass*>* const FRestrict sources, - FList<ParticleClass*>* FRestrict const* FRestrict directNeighbors, const int size) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - // Each particles targeted is impacted by the particles sources - long inc = sources->getSize(); - if(targets == sources){ - inc -= 1; - } - for(int idx = 0 ; idx < size ; ++idx){ - inc += directNeighbors[idx]->getSize(); - } - - typename FList<ParticleClass*>::BasicIterator iter(*targets); - while( iter.isValide() ){ - iter.value()->setDataDown(iter.value()->getDataDown() + inc); - iter.progress(); - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - -}; - - -/** This function test the octree to be sure that the fmm algorithm - * has worked completly. - */ -template< class ParticleClass, class CellClass, template<class ParticleClass> class LeafClass, int TreeHeight, int SizeSubLevels> -void ValidateFMMAlgo(FOctree<ParticleClass, CellClass, LeafClass, TreeHeight , SizeSubLevels>* const tree){ - std::cout << "Check Result\n"; - int NbPart = 0; - { // Check that each particle has been summed with all other - typename FOctree<ParticleClass, CellClass, LeafClass, TreeHeight, SizeSubLevels>::Iterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - do{ - if(octreeIterator.getCurrentCell()->getDataUp() != octreeIterator.getCurrentListSources()->getSize() ){ - std::cout << "Problem P2M : " << (octreeIterator.getCurrentCell()->getDataUp() - octreeIterator.getCurrentListSources()->getSize()) << "\n"; - } - NbPart += octreeIterator.getCurrentListSources()->getSize(); - } while(octreeIterator.moveRight()); - } - { // Ceck if there is number of NbPart summed at level 1 - typename FOctree<ParticleClass, CellClass, LeafClass, TreeHeight, SizeSubLevels>::Iterator octreeIterator(tree); - octreeIterator.moveDown(); - long res = 0; - do{ - res += octreeIterator.getCurrentCell()->getDataUp(); - } while(octreeIterator.moveRight()); - if(res != NbPart){ - std::cout << "Problem M2M at level 1 : " << res << "\n"; - } - } - { // Ceck if there is number of NbPart summed at level 1 - typename FOctree<ParticleClass, CellClass, LeafClass, TreeHeight, SizeSubLevels>::Iterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - for(int idxLevel = TreeHeight - 1 ; idxLevel > 1 ; --idxLevel ){ - long res = 0; - do{ - res += octreeIterator.getCurrentCell()->getDataUp(); - } while(octreeIterator.moveRight()); - if(res != NbPart){ - std::cout << "Problem M2M at level " << idxLevel << " : " << res << "\n"; - } - octreeIterator.moveUp(); - octreeIterator.gotoLeft(); - } - } - { // Check that each particle has been summed with all other - typename FOctree<ParticleClass, CellClass, LeafClass, TreeHeight, SizeSubLevels>::Iterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - do{ - typename FList<ParticleClass*>::BasicIterator iter(*octreeIterator.getCurrentListTargets()); - - const bool isUsingTsm = (octreeIterator.getCurrentListTargets() != octreeIterator.getCurrentListSources()); - - while( iter.isValide() ){ - // If a particles has been impacted by less than NbPart - 1 (the current particle) - // there is a problem - if( (!isUsingTsm && iter.value()->getDataDown() != NbPart - 1) || - (isUsingTsm && iter.value()->getDataDown() != NbPart) ){ - std::cout << "Problem L2P + P2P : " << iter.value()->getDataDown() << "\n"; - } - iter.progress(); - } - } while(octreeIterator.moveRight()); - } - - std::cout << "Done\n"; -} - - - -#endif //FTESTKERNELS_HPP - -// [--LICENSE--] diff --git a/Sources/Components/FTestParticle.hpp b/Sources/Components/FTestParticle.hpp deleted file mode 100644 index fdbed622a..000000000 --- a/Sources/Components/FTestParticle.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef FTESTPARTICLE_HPP -#define FTESTPARTICLE_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "FBasicParticle.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FTestParticle -* Please read the license -* -* This class is used in the FTestKernels, please -* look at this class to know whit it is. -*/ -class FTestParticle : public FBasicParticle { -protected: - // To store data during downard pass - long dataDown; -public: - FTestParticle(): dataDown(0){ - } - - /** Default destructor */ - virtual ~FTestParticle(){ - } - - long getDataDown() const { - return this->dataDown; - } - - void setDataDown(const long inData){ - this->dataDown = inData; - } -}; - - -#endif //FTESTPARTICLE_HPP - -// [--LICENSE--] diff --git a/Sources/Components/FTypedLeaf.hpp b/Sources/Components/FTypedLeaf.hpp deleted file mode 100644 index dbfee6fed..000000000 --- a/Sources/Components/FTypedLeaf.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef FTYPEDLEAF_HPP -#define FTYPEDLEAF_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Containers/FList.hpp" -#include "../Utils/FAssertable.hpp" -#include "FAbstractLeaf.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FTypedLeaf -* @brief -* Please read the license -* This class is used to enable the use of typed particles -* (source XOR target) or simple system (source AND target) -*/ -template< class ParticleClass > -class FTypedLeaf : public FAbstractLeaf<ParticleClass>, public FAssertable { - FList<ParticleClass*> sources; - FList<ParticleClass*> targets; - -public: - /** Default destructor */ - virtual ~FTypedLeaf(){ - } - - /** - * To add a new particle in the leaf - * @param particle the new particle - */ - void push(ParticleClass* const particle){ - if(particle->isTarget()) this->targets.pushFront(particle); - else if(particle->isSource()) this->sources.pushFront(particle); - else assert(false, "Error particle has undefined type.", __LINE__, __FILE__); - } - - /** - * To get all the sources in a leaf - * @return a pointer to the list of particles that are sources - */ - FList<ParticleClass*>* getSources() { - return &this->sources; - } - - /** - * To get all the target in a leaf - * @return a pointer to the list of particles that are targets - */ - FList<ParticleClass*>* getTargets() { - return &this->targets; - } - -}; - - -#endif //FTYPEDLEAF_HPP - -// [--LICENSE--] diff --git a/Sources/Containers/FList.hpp b/Sources/Containers/FList.hpp deleted file mode 100644 index 14b1436b2..000000000 --- a/Sources/Containers/FList.hpp +++ /dev/null @@ -1,282 +0,0 @@ -#ifndef FLIST_HPP -#define FLIST_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FGlobal.hpp" - -/** - * @author Berenger Bramas (berenger.bramas@inria.fr) - * @class FList - * Please read the license - * - * This class is a linked list container. - * It is a very basic list to enable strong performance. - * - * Please refere to unit test flistUTest.cpp to know more. - */ -template< class Object > -class FList { - /** A list node */ - struct Node { - Object target; //< Object of the node - Node* next; //< Next node - }; - - Node* root; //< Root node, NULL if size is 0 - int size; //< Elements in the list - - /** - * Copy a list into current object - * The current list has to be empty when this function is called - */ - void copy(const FList& other){ - const Node* FRestrict otherRoot = other.root; - Node * FRestrict * myRoot = &this->root; - while(otherRoot){ - (*myRoot) = new Node; - (*myRoot)->target = otherRoot->target; - - myRoot = &(*myRoot)->next; - otherRoot = otherRoot->next; - } - *myRoot = 0; - this->size = other.size; - } - -public: - /** Constructor (of an empty list) */ - FList() : root(0) , size(0) { - } - - /** Desctructor */ - virtual ~FList(){ - clear(); - } - - /** - * Copy operator - * This will clear the current list before copying - * @param other the source list - * @return the current list as a reference - */ - FList& operator=(const FList& other){ - if(this != &other){ - clear(); - copy(other); - } - return *this; - } - - /** - * Copy constructor - * @param other the source/original list - */ - FList(const FList& other): root(0) , size(0) { - copy(other); - } - - /** - * To clear the list - * Size is 0 after calling this function - */ - void clear(){ - while(this->root){ - Node*const FRestrict next = this->root->next; - delete this->root; - this->root = next; - } - this->size = 0; - } - - /** - * Push an element in the front of the list - * @param inObject the object to insert - */ - void pushFront(Object& inObject){ - Node* newNode = new Node; - newNode->target = inObject; - newNode->next = this->root; - - this->root = newNode; - ++this->size; - } - - /** - * Push an element in the front of the list - * used when type is pointer and like [TYPE* const] object - * @param inObject the object to insert - */ - void pushFront(Object const inObject){ - Node* newNode = new Node; - newNode->target = inObject; - newNode->next = this->root; - - this->root = newNode; - ++this->size; - } - - /** - * To get front value (last pushed value) - * if size == 0 then defaultValue is returned - * the list is unchanged after this function - * @param defaultValue as the returned value in case size == 0, equal Object() if no param as passed - * @return first value if exists or defaultValue otherwise - */ - Object& front(Object& defaultValue = Object()){ - if(this->size) return this->root->target; - else return defaultValue; - } - - /** - * To get front value as const - * if size == 0 then defaultValue is return - * the list is unchanged after this function - * @param defaultValue as the returned value in case size == 0, equal Object() if no param as passed - * @return first value if exists or defaultValue otherwise - */ - const Object& front(const Object& defaultValue = Object()) const { - if(this->size) return this->root->target; - else return defaultValue; - } - - /** - * To get the front value and remove it from the list - * @return first value - * @warning you must check the list's size before calling this function! - */ - Object popFront(){ - --this->size; - Node* newNode = this->root; - this->root = this->root->next; - - Object value = newNode->target; - delete newNode; - - return value; - } - - /** - * To get the number of elements in the list - * @return size - */ - int getSize() const{ - return this->size; - } - - /** - * This iterator allow accessing list's elements - * If you change the target list pointed by an iterator - * you cannot used the iterator any more. - * <code> - * FList<int> values; <br> - * // inserting ... <br> - * FList<int>::BasicIterator iter(values); <br> - * while( iter.isValide() ){ <br> - * iter.value() += 1; <br> - * iter.progress(); <br> - * } <br> - * </code> - */ - class BasicIterator { - private: - Node* iter; //< current node on the list - - public: - /** - * Constructor needs the target list - * @param the list to iterate on - */ - BasicIterator(FList& list) : iter(list.root){ - } - - /** To progress on the list */ - void progress(){ - if(this->iter) this->iter = this->iter->next; - } - - /** - * Current pointed value - * current iterator must be valide (isValide()) to use this function - */ - Object& value(){ - return this->iter->target; - } - - /** - * Current pointed value - * current iterator must be valide (isValide()) to use this function - */ - const Object& value() const{ - return this->iter->target; - } - - /** - * To know if an iterator is at the end of the list - * @return true if the current iterator can progress and access to value, else false - */ - bool isValide() const{ - return iter; - } - - }; - - /** - * This iterator allow accessing list's elements - * If you change the target list pointed by an iterator - * you cannot used the iterator any more. - * <code> - * FList<int> values; <br> - * // inserting ... <br> - * FList<int>::ConstBasicIterator iter(values); <br> - * while( iter.isValide() ){ <br> - * iter.value() += 1; <br> - * iter.progress(); <br> - * } <br> - * </code> - */ - class ConstBasicIterator { - private: - const Node* iter; //< current node on the list - - public: - /** - * Constructor needs the target list - * @param the list to iterate on - */ - ConstBasicIterator(const FList& list) : iter(list.root){ - } - - /** to progress on the list */ - void progress(){ - if(this->iter) this->iter = this->iter->next; - } - - /** - * Current pointed value - * current iterator must be valide (isValide()) to use this function - */ - Object value(){ - return this->iter->target; - } - - /** - * Current pointed value - * current iterator must be valide (isValide()) to use this function - */ - const Object& value() const{ - return this->iter->target; - } - - /** - * To know if an iterator is at the end of the list - * @return true if the current iterator can progress and access to value, else false - */ - bool isValide() const{ - return iter; - } - }; - -}; - -#endif //FLIST_HPP -// [--LICENSE--] diff --git a/Sources/Containers/FOctree.hpp b/Sources/Containers/FOctree.hpp deleted file mode 100644 index 3e61a3ed4..000000000 --- a/Sources/Containers/FOctree.hpp +++ /dev/null @@ -1,788 +0,0 @@ -#ifndef FOCTREE_HPP -#define FOCTREE_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "FSubOctree.hpp" - -#include "../Utils/FGlobal.hpp" -#include "../Utils/F3DPosition.hpp" -#include "../Utils/FMath.hpp" -#include "FTreeCoordinate.hpp" - -#include "../Utils/FAssertable.hpp" - -/** - * @author Berenger Bramas (berenger.bramas@inria.fr) - * @class FOctree - * Please read the license - * - * This class is an octree container. - * - * Please refere to testOctree.cpp to see an example. - * <code> - * // can be used as : <br> - * FOctree<TestParticle, TestCell, 10, 3> tree(1.0,F3DPosition(0.5,0.5,0.5)); - * </code> - * - * Particles and cells has to respect the Abstract class definition. - * Particle must extend {FExtendPosition} - * Cell must extend extend {FExtendPosition,FExtendMortonIndex} - */ -template< class ParticleClass, class CellClass, template <class ParticleClass> class LeafClass, int OctreeHeight, int SubtreeHeight = 3> -class FOctree { - FReal boxWidthAtLevel[OctreeHeight]; //< to store the width of each boxs at all levels - FSubOctree< ParticleClass, CellClass , LeafClass> root; //< root suboctree - - const F3DPosition boxCenter; //< the space system center - const F3DPosition boxCorner; //< the space system corner (used to compute morton index) - - const FReal boxWidth; //< the space system width - - const int height; //< tree height - const int leafIndex; //< index of leaf int array - - /** Forbiden copy operator */ - FOctree& operator=(const FOctree&) { - return *this; - } - - /** Forbiden copy constructor */ - FOctree(const FOctree&) { - } - - /** - * Get morton index from a position for the leaf leavel - * @param inPosition position to compute - * @return the morton index - */ - MortonIndex getLeafMortonFromPosition(const F3DPosition& inPosition) const { - // box coordinate to host the particle - FTreeCoordinate host; - // position has to be relative to corner not center - host.setX( getTreeCoordinate( inPosition.getX() - this->boxCorner.getX() )); - host.setY( getTreeCoordinate( inPosition.getY() - this->boxCorner.getY() )); - host.setZ( getTreeCoordinate( inPosition.getZ() - this->boxCorner.getZ() )); - return host.getMortonIndex(leafIndex); - } - - /** - * Get the box number from a position - * at a position POS with a leaf level box width of WI, the position is RELATIVE_TO_CORNER(POS)/WI - * @param inRelativePosition a position from the corner of the box - * @return the box num at the leaf level that contains inRelativePosition - */ - long getTreeCoordinate(const FReal inRelativePosition) const { - const FReal indexFReal = inRelativePosition / this->boxWidthAtLevel[this->leafIndex]; - const long index = FMath::dfloor(indexFReal); - if( index && FMath::LookEqual(inRelativePosition, this->boxWidthAtLevel[this->leafIndex] * index ) ){ - return index - 1; - } - return index; - } - -public: - /** - * Constructor - * @param inBoxWidth box width for this simulation - * @param inBoxCenter box center for this simulation - */ - FOctree(const FReal inBoxWidth, const F3DPosition& inBoxCenter) - : root(0, 0, SubtreeHeight, 1), boxCenter(inBoxCenter), boxCorner(inBoxCenter - (inBoxWidth/2)), boxWidth(inBoxWidth), - height(OctreeHeight) , leafIndex(OctreeHeight-1) { - FReal tempWidth = this->boxWidth; - // pre compute box width for each level - for(int indexLevel = 0; indexLevel < this->height; ++indexLevel ){ - this->boxWidthAtLevel[indexLevel] = tempWidth; - tempWidth /= 2.0; - } - } - - /** Desctructor */ - virtual ~FOctree() { - } - - /** - * Insert a particle on the tree - * algorithm is : - * Compute morton index for the particle - * ask node to insert this particle - * @param inParticle the particle to insert (must inherite from FAbstractParticle) - */ - void insert(ParticleClass* const inParticle){ - const MortonIndex particleIndex = getLeafMortonFromPosition( inParticle->getPosition() ); - root.insert( particleIndex, inParticle, this->height, this->boxWidthAtLevel); - } - - /** - * The class works on suboctree. Most of the resources needed - * are avaiblable by using FAbstractSubOctree. But when accessing - * to the leaf we have to use FSubOctree or FSubOctreeWithLeafs - * depending if we are working on the bottom of the tree. - */ - union SubOctreeTypes { - FAbstractSubOctree<ParticleClass,CellClass,LeafClass>* tree; //< Usual pointer to work - FSubOctree<ParticleClass,CellClass,LeafClass>* middleTree; //< To access to sub-octree under - FSubOctreeWithLeafs<ParticleClass,CellClass,LeafClass>* leafTree;//< To access to particles lists - }; - - /** - * This class is a const SubOctreeTypes - */ - union SubOctreeTypesConst { - const FAbstractSubOctree<ParticleClass,CellClass,LeafClass>* tree; //< Usual pointer to work - const FSubOctree<ParticleClass,CellClass,LeafClass>* middleTree; //< To access to sub-octree under - const FSubOctreeWithLeafs<ParticleClass,CellClass,LeafClass>* leafTree;//< To access to particles lists - }; - - /** - * This has to be used to iterate on an octree - * It simply stores an pointer on a suboctree and moves to right/left/up/down. - * Please refere to testOctreeIter file to see how it works. - * - * <code> - * FOctree<TestParticle, TestCell, NbLevels, NbSubLevels>::Iterator octreeIterator(&tree); <br> - * octreeIterator.gotoBottomLeft(); <br> - * for(int idx = 0 ; idx < NbLevels - 1; ++idx ){ <br> - * do{ <br> - * // ... <br> - * } while(octreeIterator.moveRight()); <br> - * octreeIterator.moveUp(); <br> - * octreeIterator.gotoLeft(); <br> - * } <br> - * <code> - * Remark : - * It uses the left right limit on each suboctree and their morton index. - * Please have a look to the move functions to understand how the system is working. - */ - class Iterator : protected FAssertable { - SubOctreeTypes current; //< Current suboctree - - long currentLocalIndex; //< Current index (array position) in the current_suboctree.cells[ currentLocalLevel ] - int currentLocalLevel; //< Current level in the current suboctree - - /** - * To know what is the left limit on the current level on the current subtree - * @retrun suboctree.left_limit >> 3 * diff(leaf_index, current_index). - */ - static long TransposeIndex(const long indexInLeafLevel, const int distanceFromLeafLevel) { - return indexInLeafLevel >> (3 * distanceFromLeafLevel); - } - - - public: - /** - * Constructor - * @param inTarget the octree to iterate on - * After building a iterator, this one is positioned at the level 0 - * of the root (level 1 of octree) at the left limit index - */ - Iterator(FOctree* const inTarget) - : currentLocalIndex(0) , currentLocalLevel(0) { - assert(inTarget, "Target for Octree::Iterator cannot be null", __LINE__, __FILE__); - assert(inTarget->root.getRightLeafIndex() >= 0, "Octree seems to be empty, getRightLeafIndex == 0", __LINE__, __FILE__); - - // Start by the root - this->current.tree = &inTarget->root; - // On the left limit - this->currentLocalIndex = TransposeIndex(this->current.tree->getLeftLeafIndex(), (this->current.tree->getSubOctreeHeight() - this->currentLocalLevel - 1) ); - } - - Iterator() : currentLocalIndex(0),currentLocalLevel(0) { - current.tree = 0; - } - - /** Copy constructor - * @param other source iterator to copy - */ - Iterator(const Iterator& other){ - this->current = other.current ; - this->currentLocalLevel = other.currentLocalLevel ; - this->currentLocalIndex = other.currentLocalIndex ; - } - - /** Copy operator - * @param other source iterator to copy - * @return this after copy - */ - Iterator& operator=(const Iterator& other){ - this->current = other.current ; - this->currentLocalLevel = other.currentLocalLevel ; - this->currentLocalIndex = other.currentLocalIndex ; - return *this; - } - - /** - * Move iterator to the top! (level 0 of root suboctree, level 1 of octree) - * after this function : index = left limit at root level - * the Algorithm is : - * going to root suboctree - * going to the first level and most left node - */ - void gotoTop(){ - while(this->current.tree->hasParent()){ - this->current.tree = this->current.tree->getParent(); - } - this->currentLocalLevel = 0; - this->currentLocalIndex = TransposeIndex(this->current.tree->getLeftLeafIndex(), (this->current.tree->getSubOctreeHeight() - 1) ); - } - - /** - * Move iterator to the bottom left place - * We are on a leaf a the most left node - * the Algorithm is : - * first go to top - * then stay on the left and go downward - */ - void gotoBottomLeft(){ - gotoTop(); - while(1) { - this->currentLocalLevel = this->current.tree->getSubOctreeHeight() - 1; - this->currentLocalIndex = this->current.tree->getLeftLeafIndex(); - if( isAtLeafLevel() ){ - return; - } - this->current.tree = this->current.middleTree->leafs( this->currentLocalIndex ); - } - } - - /** - * Move iterator to the left place at the same level - * if needed we go on another suboctree but we stay on at the same level - * the Algorithm is : - * go to top - * go downard until we are a the same level - */ - void gotoLeft(){ - // Function variables - const int currentLevel = level(); - - // Goto root sutoctree - while( this->current.tree->hasParent() ){ - this->current.tree = this->current.tree->getParent(); - } - - // Go down on the left until arriving on the same global level - while( this->current.tree->getSubOctreeHeight() + this->current.tree->getSubOctreePosition() - 1 < currentLevel ) { - this->current.tree = this->current.middleTree->leafs(this->current.tree->getLeftLeafIndex()); - } - - // Level still unchanged we only go to the left - // The left limit on this tree at the level we want to stay - this->currentLocalIndex = TransposeIndex(this->current.tree->getLeftLeafIndex(), (this->current.tree->getSubOctreeHeight() - this->currentLocalLevel - 1)); - } - - /** - * Move iterator to the right place at the same level - * if needed we go on another suboctree but we stay on at the same level - * the Algorithm is : - * go to top - * go downard until we are a the same level - */ - void gotoRight(){ - // Function variables - const int currentLevel = level(); - // Goto root sutoctree - while( this->current.tree->hasParent() ){ - this->current.tree = this->current.tree->getParent(); - } - // Go down on the left until arriving on the same global level - while( this->current.tree->getSubOctreeHeight() + this->current.tree->getSubOctreePosition() - 1 < currentLevel ) { - this->current.tree = this->current.middleTree->leafs(this->current.tree->getRightLeafIndex()); - } - // Level still unchanged we only go to the left - // The left limit on this tree at the level we want to stay - this->currentLocalIndex = TransposeIndex(this->current.tree->getRightLeafIndex(), (this->current.tree->getSubOctreeHeight() - this->currentLocalLevel - 1)); - } - - /** - * Goto the next value on the right at the same level - * - * The algorithm here is : - * As long as we are on the right limit, go to the parent suboctree - * if we are on the root and on the right then return (there is no more data on the right) - * - * After that point we do not know where we are but we know that there is some data - * on the right (without knowing our position!) - * - * We progress on the brother to find an allocated cell (->) - * for example if we are on index 2 we will look until 8 = 2 | 7 + 1 - * if we arrive a 8 without finding a cell we go upper and do the same - * we know we will find something because we are not at the right limit - * - * We find an allocated cell. - * We have to go down, we go on the left child of this cells - * until : the current level if we did not have change the current suboctree - * or : the leaf level - * - * In the second case, it meanse we need to change octree downward - * but it is easy because we can use the left limit! - * - * @return true if we succeed to go to the right, else false - */ - bool moveRight(){ - // Function variables - SubOctreeTypes workingTree = this->current; // To cover parent other sub octre - long workingLevel = this->currentLocalLevel; // To know where we are - long workingIndex = this->currentLocalIndex; // To know where we are - - // -- First we have to go in a tree where we can move on the right -- - // Number of time we go into parent subtree - int countUpward = 0; - // We stop when we can right move or if there is no more parent (root) - while( workingIndex == TransposeIndex(workingTree.tree->getRightLeafIndex(), (workingTree.tree->getSubOctreeHeight() - workingLevel - 1) ) - && workingTree.tree->hasParent() ){ - // Goto the leaf level into parent at current_tree.position_into_parent_array - workingIndex = workingTree.tree->getIndexInParent(); - workingTree.tree = workingTree.tree->getParent(); - workingLevel = workingTree.tree->getSubOctreeHeight() - 1; - // inc counter - ++countUpward; - } - - // Do we stop because we are on the root (means we cannot move right?) - if( workingIndex < TransposeIndex(workingTree.tree->getRightLeafIndex(), (workingTree.tree->getSubOctreeHeight() - workingLevel - 1) ) ){ - // Move to the first right cell pointer(!) - ++workingIndex; - - // Maybe it is null, but we know there is almost one cell on the right - // we need to find it - if( !workingTree.tree->cellsAt(workingLevel)[workingIndex] ){ - // While we are not on a allocated cell - while( true ){ - // Test element on the right (test brothers) - const long rightLimite = (workingIndex | 7) + 1; - while( workingIndex < rightLimite && !workingTree.tree->cellsAt(workingLevel)[workingIndex]){ - ++workingIndex; - } - // Stop if we are on an allocated cell - if( workingTree.tree->cellsAt(workingLevel)[workingIndex] ){ - break; - } - // Else go to the upper level - --workingLevel; - workingIndex >>= 3; - } - } - - // if wokring tree != current tree => working tree leafs level ; else current level - const int objectiveLevel = (countUpward ? workingTree.tree->getSubOctreeHeight() - 1 : this->currentLocalLevel ); - - // We need to go down as left as possible - while( workingLevel != objectiveLevel ){ - ++workingLevel; - workingIndex <<= 3; - const long rightLimite = (workingIndex | 7); // not + 1 because if the 7th first are null it must be the 8th! - while( workingIndex < rightLimite && !workingTree.tree->cellsAt(workingLevel)[workingIndex]){ - ++workingIndex; - } - } - - // Do we change from the current sub octree? - if( countUpward ){ - // Then we simply need to go down the same number of time - workingTree.tree = workingTree.middleTree->leafs(workingIndex); - while( --countUpward ){ - workingTree.tree = workingTree.middleTree->leafs(workingTree.tree->getLeftLeafIndex()); - } - // level did not change, simpli set octree and get left limit of this octree at the current level - this->current = workingTree; - this->currentLocalIndex = TransposeIndex(workingTree.tree->getLeftLeafIndex(), (workingTree.tree->getSubOctreeHeight() - this->currentLocalLevel - 1) ); - } - else{ - // We are on the right tree - this->currentLocalIndex = workingIndex; - } - - return true; - } - return false; - } - - /** - * Move to the upper level - * It may cause to change the suboctree we are working on - * but we are using the same morton index >> 3 - * @return true if succeed - */ - bool moveUp() { - // It is on the top level? - if( this->currentLocalLevel ){ - // No so simply go up - --this->currentLocalLevel; - this->currentLocalIndex >>= 3; - } - // Yes need to change suboctree - else if( this->current.tree->hasParent() ){ - this->currentLocalIndex = this->current.tree->getIndexInParent(); - this->current.tree = this->current.tree->getParent(); - this->currentLocalLevel = this->current.tree->getSubOctreeHeight() - 1; - } - else{ - return false; - } - return true; - } - - /** - * Move down - * It may cause to change the suboctree we are working on - * We point on the first child found from left to right in the above - * level - * @return true if succeed - */ - bool moveDown(){ - if( !isAtLeafLevel() ){ - // We are on the leaf of the current suboctree? - if(this->currentLocalLevel + 1 == this->current.tree->getSubOctreeHeight()){ - // Yes change sub octree - this->current.tree = this->current.middleTree->leafs(this->currentLocalIndex); - this->currentLocalIndex = 0; - this->currentLocalLevel = 0; - } - // No simply go down - else{ - ++this->currentLocalLevel; - this->currentLocalIndex <<= 3; - } - // Find the first allocated cell from left to right - while(!this->current.tree->cellsAt(this->currentLocalLevel)[this->currentLocalIndex]){ - ++this->currentLocalIndex; - } - return true; - } - return false; - } - - /** - * To know if we are not on the root level - * @return true if we can move up - */ - bool canProgressToUp() const { - return this->currentLocalLevel || this->current.tree->hasParent(); - } - - /** - * To know if we are not on the leafs level - * @return true if we can move down - */ - bool canProgressToDown() const { - return !isAtLeafLevel(); - } - - /** - * To know if we are on the leafs level - * @return true if we are at the bottom of the tree - */ - bool isAtLeafLevel() const { - return level() + 1 == OctreeHeight; - } - - /** - * To know the current level (not local but global) - * @return the level in the entire octree - */ - int level() const { - return this->currentLocalLevel + this->current.tree->getSubOctreePosition(); - } - - /** To access the current particles list - * You have to be at the leaf level to call this function! - * @return current element list - */ - FList<ParticleClass*>* getCurrentListSources() { - return this->current.leafTree->getLeafSources(this->currentLocalIndex); - } - - /** To access the current particles list - * You have to be at the leaf level to call this function! - * @return current element list - */ - FList<ParticleClass*>* getCurrentListTargets() { - return this->current.leafTree->getLeafTargets(this->currentLocalIndex); - } - - /** Get the current pointed cell - * @return current cell element - */ - CellClass* getCurrentCell() { - return this->current.tree->cellsAt(this->currentLocalLevel)[this->currentLocalIndex]; - } - - /** Get the child of the current cell - * This function return an array of CellClass (array size = 8) - * User has to test each case to know if there is a cell - * @return the child array - */ - CellClass** getCurrentChild() { - // are we at the bottom of the suboctree - if(this->current.tree->getSubOctreeHeight() - 1 == this->currentLocalLevel ){ - // then return first level of the suboctree under - return &this->current.middleTree->leafs(this->currentLocalIndex)->cellsAt(0)[0]; - } - else{ - // else simply return the array at the right position - return &this->current.tree->cellsAt(this->currentLocalLevel + 1)[this->currentLocalIndex << 3]; - } - } - - /** Get the Morton index of the current cell pointed by the iterator - * @return The global morton index - * <code>iter.getCurrentGlobalIndex();<br> - * // is equivalent to :<br> - * iter.getCurrentCell()->getMortonIndex();</code> - */ - MortonIndex getCurrentGlobalIndex() const{ - return this->current.tree->cellsAt(this->currentLocalLevel)[this->currentLocalIndex]->getMortonIndex(); - } - - }; - - // To be able to access octree root & data - friend class Iterator; - - /////////////////////////////////////////////////////////////////////////// - // This part is related to the FMM algorithm (needed by M2M,M2L,etc.) - /////////////////////////////////////////////////////////////////////////// - - /** This function return a cell (if it exists) from a morton index and a level - * @param inIndex the index of the desired cell - * @param inLevel the level of the desired cell (cannot be infered from the index) - * @return the cell if it exist or null (0) - * This function starts from the root until it find a missing cell or the right cell - */ - CellClass* getCell(const MortonIndex inIndex, const int inLevel) const{ - SubOctreeTypesConst workingTree; - workingTree.tree = &this->root; - const MortonIndex treeSubLeafMask = ~(~0x00LL << (3 * workingTree.tree->getSubOctreeHeight() )); - - // Find the suboctree a the correct level - while(inLevel >= workingTree.tree->getSubOctreeHeight() + workingTree.tree->getSubOctreePosition()) { - // compute the leaf index - const MortonIndex fullIndex = inIndex >> (3 * (inLevel + 1 - (workingTree.tree->getSubOctreeHeight() + workingTree.tree->getSubOctreePosition()) ) ); - // point to next suboctree - workingTree.tree = workingTree.middleTree->leafs(treeSubLeafMask & fullIndex); - if(!workingTree.tree) return 0; - } - - // compute correct index in the array - const MortonIndex treeLeafMask = ~(~0x00LL << (3 * (inLevel + 1 - workingTree.tree->getSubOctreePosition()) )); - return workingTree.tree->cellsAt(inLevel - workingTree.tree->getSubOctreePosition())[treeLeafMask & inIndex]; - } - - - /** This function fill a array with the neighbors of a cell - * it does not put the brothers in the array (brothers are cells - * at the same level with the same parent) because they are of course - * direct neighbors. - * There is a maximum of 26 (3*3*3-1) direct neighbors - * @param inNeighbors the array to store the elements - * @param inIndex the index of the element we want the neighbors - * @param inLevel the level of the element - * @return the number of neighbors - */ - int getNeighborsNoBrothers(CellClass* inNeighbors[26], const MortonIndex inIndex, const int inLevel) const { - FTreeCoordinate center; - center.setPositionFromMorton(inIndex, inLevel); - - const long limite = FMath::pow(2,inLevel); - - int idxNeighbors = 0; - - // We test all cells around - for(long idxX = -1 ; idxX <= 1 ; ++idxX){ - if(!FMath::Between(center.getX() + idxX,0l,limite)) continue; - - for(long idxY = -1 ; idxY <= 1 ; ++idxY){ - if(!FMath::Between(center.getY() + idxY,0l,limite)) continue; - - for(long idxZ = -1 ; idxZ <= 1 ; ++idxZ){ - if(!FMath::Between(center.getZ() + idxZ,0l,limite)) continue; - - // if we are not on the current cell - if( !(!idxX && !idxY && !idxZ) ){ - const FTreeCoordinate other(center.getX() + idxX,center.getY() + idxY,center.getZ() + idxZ); - const MortonIndex mortonOther = other.getMortonIndex(inLevel); - // if not a brother - if( mortonOther>>3 != inIndex>>3 ){ - // get cell - CellClass* const cell = getCell(mortonOther, inLevel); - // add to list if not null - if(cell) inNeighbors[idxNeighbors++] = cell; - } - } - } - } - } - - return idxNeighbors; - } - - - /** This function return an adresse of cell array from a morton index and a level - * - * @param inIndex the index of the desired cell array has to contains - * @param inLevel the level of the desired cell (cannot be infered from the index) - * @return the cell if it exist or null (0) - * - */ - CellClass** getCellPt(const MortonIndex inIndex, const int inLevel) const{ - SubOctreeTypesConst workingTree; - workingTree.tree = &this->root; - - const MortonIndex treeMiddleMask = ~(~0x00LL << (3 * workingTree.tree->getSubOctreeHeight() )); - - // Find the suboctree a the correct level - while(inLevel >= workingTree.tree->getSubOctreeHeight() + workingTree.tree->getSubOctreePosition()) { - // compute the leaf index - const MortonIndex fullIndex = inIndex >> 3 * (inLevel + 1 - (workingTree.tree->getSubOctreeHeight() + workingTree.tree->getSubOctreePosition()) ); - // point to next suboctree - workingTree.tree = workingTree.middleTree->leafs(treeMiddleMask & fullIndex); - if(!workingTree.tree) return 0; - } - - // Be sure there is a parent allocated - const int levelInTree = inLevel - workingTree.tree->getSubOctreePosition(); - if( levelInTree && !workingTree.tree->cellsAt(levelInTree - 1)[~(~0x00LL << (3 * levelInTree )) & (inIndex>>3)]){ - return 0; - } - - // compute correct index in the array and return the @ in array - const MortonIndex treeLeafMask = ~(~0x00LL << (3 * (levelInTree + 1 ) )); - return &workingTree.tree->cellsAt(levelInTree)[treeLeafMask & inIndex]; - } - - /** This function fill an array with the distant neighbors of a cell - * @param inNeighbors the array to store the elements - * @param inIndex the index of the element we want the neighbors - * @param inLevel the level of the element - * @return the number of neighbors - */ - int getDistantNeighbors(CellClass* inNeighbors[208], const MortonIndex inIndex, const int inLevel) const{ - // Take the neighbors != brothers - CellClass* directNeighbors[26]; - const int nbDirectNeighbors = getNeighborsNoBrothers(directNeighbors,inIndex,inLevel); - // Then take each child of the parent's neighbors if not in directNeighbors - // Father coordinate - FTreeCoordinate center; - center.setPositionFromMorton(inIndex>>3, inLevel-1); - // Limite at parent level - const long limite = FMath::pow(2,inLevel-1); - - int idxNeighbors = 0; - // We test all cells around - for(long idxX = -1 ; idxX <= 1 ; ++idxX){ - if(!FMath::Between(center.getX() + idxX,0l,limite)) continue; - - for(long idxY = -1 ; idxY <= 1 ; ++idxY){ - if(!FMath::Between(center.getY() + idxY,0l,limite)) continue; - - for(long idxZ = -1 ; idxZ <= 1 ; ++idxZ){ - if(!FMath::Between(center.getZ() + idxZ,0l,limite)) continue; - - // if we are not on the current cell - if( !(!idxX && !idxY && !idxZ) ){ - - const FTreeCoordinate other(center.getX() + idxX,center.getY() + idxY,center.getZ() + idxZ); - const MortonIndex mortonOther = other.getMortonIndex(inLevel-1); - // Get child - CellClass** const cells = getCellPt(mortonOther<<3, inLevel); - - // If there is one or more child - if(cells){ - // For each child - for(int idxCousin = 0 ; idxCousin < 8 ; ++idxCousin){ - if(cells[idxCousin]){ - // Test if it is a direct neighbor - bool existInDirectNeigh = false; - for(int idxDirectNeigh = 0 ; idxDirectNeigh < nbDirectNeighbors ; ++idxDirectNeigh){ - if( cells[idxCousin] == directNeighbors[idxDirectNeigh] ){ - existInDirectNeigh = true; - break; - } - } - // add to neighbors - if(!existInDirectNeigh){ - inNeighbors[idxNeighbors++] = cells[idxCousin]; - } - } - } - } - } - } - } - } - - return idxNeighbors; - } - - - /** This function return a cell (if it exists) from a morton index and a level - * @param inIndex the index of the desired cell - * @param inLevel the level of the desired cell (cannot be infered from the index) - * @return the cell if it exist or null (0) - * - */ - FList<ParticleClass*>* getLeafSources(const MortonIndex inIndex){ - SubOctreeTypes workingTree; - workingTree.tree = &this->root; - const MortonIndex treeSubLeafMask = ~(~0x00LL << (3 * workingTree.tree->getSubOctreeHeight() )); - - // Find the suboctree a the correct level - while(leafIndex >= workingTree.tree->getSubOctreeHeight() + workingTree.tree->getSubOctreePosition()) { - // compute the leaf index - const MortonIndex fullIndex = inIndex >> (3 * (leafIndex + 1 - (workingTree.tree->getSubOctreeHeight() + workingTree.tree->getSubOctreePosition()) ) ); - // point to next suboctree - workingTree.tree = workingTree.middleTree->leafs(treeSubLeafMask & fullIndex); - if(!workingTree.tree) return 0; - } - - // compute correct index in the array - const MortonIndex treeLeafMask = ~(~0x00LL << (3 * (leafIndex + 1 - workingTree.tree->getSubOctreePosition()) )); - return workingTree.leafTree->getLeafSources(treeLeafMask & inIndex); - } - - /** This function fill an array with the neighbors of a cell - * @param inNeighbors the array to store the elements - * @param inIndex the index of the element we want the neighbors - * @param inLevel the level of the element - * @return the number of neighbors - */ - int getLeafsNeighbors(FList<ParticleClass*>* inNeighbors[26], const MortonIndex inIndex, const int inLevel){ - FTreeCoordinate center; - center.setPositionFromMorton(inIndex, inLevel); - - const long limite = FMath::pow(2,inLevel); - - int idxNeighbors = 0; - - // We test all cells around - for(long idxX = -1 ; idxX <= 1 ; ++idxX){ - if(!FMath::Between(center.getX() + idxX,0l,limite)) continue; - - for(long idxY = -1 ; idxY <= 1 ; ++idxY){ - if(!FMath::Between(center.getY() + idxY,0l,limite)) continue; - - for(long idxZ = -1 ; idxZ <= 1 ; ++idxZ){ - if(!FMath::Between(center.getZ() + idxZ,0l,limite)) continue; - - // if we are not on the current cell - if( !(!idxX && !idxY && !idxZ) ){ - const FTreeCoordinate other(center.getX() + idxX,center.getY() + idxY,center.getZ() + idxZ); - const MortonIndex mortonOther = other.getMortonIndex(inLevel); - // get cell - FList<ParticleClass*>* const leaf = getLeafSources(mortonOther); - // add to list if not null - if(leaf) inNeighbors[idxNeighbors++] = leaf; - } - } - } - } - - return idxNeighbors; - } - - -}; - -#endif //FOCTREE_HPP -// [--LICENSE--] diff --git a/Sources/Containers/FSubOctree.hpp b/Sources/Containers/FSubOctree.hpp deleted file mode 100644 index 8e6beb2c6..000000000 --- a/Sources/Containers/FSubOctree.hpp +++ /dev/null @@ -1,452 +0,0 @@ -#ifndef FSUBOCTREE_HPP -#define FSUBOCTREE_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FGlobal.hpp" -#include "../Utils/F3DPosition.hpp" -#include "../Utils/FAssertable.hpp" -#include "../Utils/FMath.hpp" -#include "../Utils/FConvert.hpp" - -#include "FTreeCoordinate.hpp" -#include "FList.hpp" - - -/** - * @author Berenger Bramas (berenger.bramas@inria.fr) - * @class FAbstractSubOctree - * Please read the license - * - * This class is a sub-octree container. - * This class is the main component of the octree. - * - * This class does not have a main root. In fact, the root - * is contained in the parent sub-octree. - * - * If the sub-octree is a middle suboctree, the leaf level is pointers - * on other suboctrees. - * - * If the sub-octree is a bottom subtree then the leaf level is pointers on - * lists<particle> - * - * This two situations are implemented in two different classes that inherite of FAbstractSubOctree. - * - * Please refere to testOctree.cpp to see an example - * @warning Give the particleClass & cellClass - */ -template< class ParticleClass, class CellClass , template <class ParticleClass> class LeafClass> -class FAbstractSubOctree : protected FAssertable{ -protected: - - CellClass*** cells; //< Potential cells, cells are allocated only if needed - FAbstractSubOctree* const parent; //< Parent suboctree (null for root) - - const long indexInParent; //< This is the index of the current octree in the parent's array - - long leftLeafIndex; //< The leaf at the left position (this is the array index to start when iterate) - long rightLeafIndex; //< The leaf at the right position (this is the last array index when iterate) - - const int subOctreeHeight; //< Height of this suboctree - const int subOctreePosition; //< Level of the current suboctree in the global tree (0 if node) - - - /** - * This function compute the morton index for the last level of this suboctree. - * suppose we have an index like : 000.010.111.001.101.110 - * and now considere that suboctree's height is 2, the morton index have to be cut as : - * [000.010].[111.001].[101.110] each part correspond to a morton index a leaf level for the - * different suboctrees. - * This is why depending on the level of the octree we need to remove extra part on the left and - * on the right. - */ - MortonIndex getLeafIndex(const MortonIndex index, const int inTreeHeight) const { - // Remove right useless part - used by child - const MortonIndex fullIndex = index >> (3 * (inTreeHeight - (this->subOctreeHeight + this->subOctreePosition) ) ); - // Remove left extra data part - used by parent - const MortonIndex treeLeafMask = ~(~0x00LL << (3 * this->subOctreeHeight )); - return treeLeafMask & fullIndex; - } - - /** - * This function creats all the intermediates cells between - * a leaf and the root. - * It is used after inserting a new leaf to have cells from leaf to root - * when computing - * @param arrayIndex the index at the leaf index of the new element - */ - void createPreviousCells(MortonIndex arrayIndex, MortonIndex inLeafCellIndex, const FReal* const inBoxWidthAtLevel){ - int indexLevel = this->subOctreeHeight - 1; - while(indexLevel >= 0 && !this->cells[indexLevel][arrayIndex]){ - this->cells[indexLevel][arrayIndex] = new CellClass(); - this->cells[indexLevel][arrayIndex]->setMortonIndex(inLeafCellIndex); - - const int realLevel = indexLevel + this->getSubOctreePosition(); - this->cells[indexLevel][arrayIndex]->setPosition(FConvert::MortonToPosition(inLeafCellIndex,realLevel,inBoxWidthAtLevel[realLevel])); - - --indexLevel; - - arrayIndex >>= 3; - inLeafCellIndex >>= 3; - } - } - - /** - * This function is initializing variables when a new leaf is inserted in the tree - * for example it updates the leaf array marges and calls createPreviousCells() - * @param arrayIndex the position of the new leaf in the leafs array - */ - void newLeafInserted(const long arrayIndex, const MortonIndex inLeafCellIndex, const FReal* const inBoxWidthAtLevel){ - createPreviousCells(arrayIndex,inLeafCellIndex, inBoxWidthAtLevel); - // Update if this is the bottom left - if(arrayIndex < this->leftLeafIndex) this->leftLeafIndex = arrayIndex; - if(arrayIndex > this->rightLeafIndex) this->rightLeafIndex = arrayIndex; - } - - /** Disable copy */ -private: - FAbstractSubOctree(const FAbstractSubOctree&){} - FAbstractSubOctree& operator=(const FAbstractSubOctree&){return *this;} - -public: - /** - * Constructor - * Allocate the cells arrays to be able to create every potential cells - * @param inParent the SubOctree parent (0 if node) - * @param inSubOctreeHeight Height of this suboctree - * @param inSubOctreePosition Level of the current suboctree in the global tree (1 if upper tree) - */ - FAbstractSubOctree(FAbstractSubOctree* const inParent, const long inIndexInParent, - const int inSubOctreeHeight, const int inSubOctreePosition) : - cells(0), parent( inParent ), indexInParent(inIndexInParent), leftLeafIndex(1 << (3 * inSubOctreeHeight)), rightLeafIndex(-1), - subOctreeHeight( inSubOctreeHeight ), subOctreePosition( inSubOctreePosition ) { - - this->cells = new CellClass**[this->subOctreeHeight]; - assert(this->cells, "Allocation failled", __LINE__, __FILE__); - - // We start at a sub-level - 8^1 - long cellsAtlevel = 8; - for( int indexLevel = 0 ; indexLevel < this->subOctreeHeight ; ++indexLevel ){ - this->cells[indexLevel] = new CellClass*[cellsAtlevel]; - assert(this->cells[indexLevel], "Allocation failled", __LINE__, __FILE__); - - for( int indexCells = 0 ; indexCells < cellsAtlevel ; ++indexCells ){ - this->cells[indexLevel][indexCells] = 0; - } - - cellsAtlevel <<= 3; // => * 8 >> 8^indexLevel - } - } - - /** - * Destructor - * Delete cells arrays and allocated cells - */ - virtual ~FAbstractSubOctree(){ - long cellsAtlevel = 8; - for( int indexLevel = 0 ; indexLevel < this->subOctreeHeight ; ++indexLevel ){ - for( int indexCells = 0 ; indexCells < cellsAtlevel ; ++indexCells ){ - if(this->cells[indexLevel][indexCells]){ - delete this->cells[indexLevel][indexCells]; - } - } - - delete [] this->cells[indexLevel]; - cellsAtlevel <<= 3; // => * 8 >> 8^indexLevel - } - - delete [] this->cells; - } - - - /** - * Insert a particle on the subtree - * @param index the morton index of the particle to insert - * @param inParticle the particle to insert (must inherite from FAbstractParticle) - * @param inParticle the inTreeHeight the height of the tree - */ - virtual void insert(const MortonIndex index, ParticleClass* const inParticle, const int inTreeHeight, const FReal* const inBoxWidthAtLevel) = 0; - - /////////////////////////////////////// - // This is the FOctree::Iterator Part - /////////////////////////////////////// - - /** Suboctree height accessor (leaf level + 1) - * @return subOctreeHeight */ - int getSubOctreeHeight() const{ - return subOctreeHeight; - } - - /** Suboctree position in the real tree - * @return subOctreePosition */ - int getSubOctreePosition() const { - return subOctreePosition; - } - - /** Return the more left leaf index - * the smallest index on the leafs array - * @return leftLeafIndex */ - long getLeftLeafIndex() const { - return leftLeafIndex; - } - - /** Return the more right leaf index - * the biggest index on the leafs array - * @return rightLeafIndex */ - long getRightLeafIndex() const { - return rightLeafIndex; - } - - /** Return the array of cells at a specious index - * @param level the level to access cells array (must be < subOctreeHeight) - * @return cells[level] */ - CellClass** cellsAt(const int level) const{ - assert(level < subOctreeHeight, "Level out of memory", __LINE__, __FILE__); - return cells[level]; - } - - /** To know if it is the root suboctree - * @return true if has parent otherwise return false */ - bool hasParent() const { - return parent; - } - - /** To get access to the parent suboctree - * @return parent */ - FAbstractSubOctree* getParent(){ - return parent; - } - - /** To get access to the parent suboctree (const version) - * @return parent */ - const FAbstractSubOctree* getParent() const{ - return parent; - } - - /** To get the index of the current suboctree in the parent leafs array - * This index can is part of the morton index of the cells contains - * in this suboctree - * @return indexInParent */ - long getIndexInParent() const{ - return indexInParent; - } -}; - - - -///////////////////////////////////////////////////////////////////////////////////// -// Last level sub octree -///////////////////////////////////////////////////////////////////////////////////// - -/** - * @author Berenger Bramas (berenger.bramas@inria.fr) - * @class FSubOctreeWithLeafs - * Please read the license - * - * This class is an sub-octree container. - * But this is the specialized bottom part, in fact the last level is composed by - * a cells array (managing by abstract class) and lists of particles. - * - * Please refere to testOctree.cpp to see an example. - * @warning Give the particleClass & cellClass - */ -template< class ParticleClass, class CellClass , template <class ParticleClass> class LeafClass> -class FSubOctreeWithLeafs : public FAbstractSubOctree<ParticleClass,CellClass,LeafClass> { -private: - - LeafClass<ParticleClass>** leafs; //< Leafs array - - /** Disable copy */ - FSubOctreeWithLeafs(const FSubOctreeWithLeafs&){} - FSubOctreeWithLeafs& operator=(const FSubOctreeWithLeafs&){return *this;} - -public: - /** - * Constructor - * Allocate the leafs array - * @param inParent the SubOctree parent (0 if node) - * @param inSubOctreeHeight Height of this suboctree - * @param inSubOctreePosition Level of the current suboctree in the global tree (1 if upper tree) - */ - FSubOctreeWithLeafs(FAbstractSubOctree<ParticleClass,CellClass,LeafClass>* const inParent, const long inIndexInParent, - const int inSubOctreeHeight, const int inSubOctreePosition) : - FAbstractSubOctree<ParticleClass,CellClass,LeafClass>(inParent, inIndexInParent, inSubOctreeHeight, inSubOctreePosition) { - - const long cellsAtLeafLevel = 1 << (3 * inSubOctreeHeight); - - this->leafs = new LeafClass<ParticleClass>*[cellsAtLeafLevel]; - assert(this->leafs, "Allocation failled", __LINE__, __FILE__); - - for( long indexLeaf = 0 ; indexLeaf < cellsAtLeafLevel ; ++indexLeaf ){ - this->leafs[indexLeaf] = 0; - } - } - - /** - * Destructor dealloc all leafs & the leaf array - */ - virtual ~FSubOctreeWithLeafs(){ - const int cellsAtLeafLevel = 1 << (3 * this->subOctreeHeight ); - for( int indexLeaf = 0 ; indexLeaf < cellsAtLeafLevel ; ++indexLeaf ){ - if(this->leafs[indexLeaf]){ - delete this->leafs[indexLeaf]; - } - } - delete [] this->leafs; - } - - /** - * Refer to FAbstractSubOctree::insert - */ - void insert(const MortonIndex index, ParticleClass* const inParticle, const int inTreeHeight, const FReal* const inBoxWidthAtLevel){ - // Get the morton index for the leaf level - const MortonIndex arrayIndex = FAbstractSubOctree<ParticleClass,CellClass,LeafClass>::getLeafIndex(index,inTreeHeight); - // is there already a leaf? - if( !this->leafs[arrayIndex] ){ - this->leafs[arrayIndex] = new LeafClass<ParticleClass>(); - FAbstractSubOctree<ParticleClass,CellClass,LeafClass>::newLeafInserted( arrayIndex , index, inBoxWidthAtLevel); - } - // add particle to leaf list - this->leafs[arrayIndex]->push(inParticle); - } - - /** To get access to leafs elements - * @param index the position of the leaf - * @return the list of particles at this index */ - FList<ParticleClass*>* getLeafSources(const int index){ - LeafClass<ParticleClass>* const leaf = this->leafs[index]; - return (leaf ? leaf->getSources(): 0); - } - - /** To get access to leafs elements - * @param index the position of the leaf - * @return the list of particles at this index */ - FList<ParticleClass*>* getLeafTargets(const int index){ - LeafClass<ParticleClass>* const leaf = this->leafs[index]; - return (leaf ? leaf->getTargets(): 0); - } - - /** To get access to leafs elements - * @param index the position of the leaf - * @return the list of particles at this index */ - const FList<ParticleClass*>* getLeafSources(const int index) const { - LeafClass<ParticleClass>* const leaf = this->leafs[index]; - return (leaf ? leaf->getSources(): 0); - } - - /** To get access to leafs elements - * @param index the position of the leaf - * @return the list of particles at this index */ - const FList<ParticleClass*>* getLeafTargets(const int index) const { - LeafClass<ParticleClass>* const leaf = this->leafs[index]; - return (leaf ? leaf->getTargets() : 0); - } - -}; - - - -///////////////////////////////////////////////////////////////////////////////////// -// Middle level sub octree -///////////////////////////////////////////////////////////////////////////////////// - -/** - * @author Berenger Bramas (berenger.bramas@inria.fr) - * @class FSubOctree - * Please read the license - * - * This class is an sub-octree container. - * This is the middle level specialized suboctree, it means that it does not contain - * leaf but pointers to other suboctree. - * These suboctrees at the last level can be FSubOctree of FSubOctreeWithLeafs depending - * if they are at the bottom of the tree or not - * - * @warning Give the particleClass & cellClass - */ -template< class ParticleClass, class CellClass , template <class ParticleClass> class LeafClass> -class FSubOctree : public FAbstractSubOctree<ParticleClass,CellClass,LeafClass> { -private: - FAbstractSubOctree<ParticleClass,CellClass,LeafClass>** subleafs; //< Last levels is composed of suboctree - - /** Disable copy */ - FSubOctree(const FSubOctree&){} - FSubOctree& operator=(const FSubOctree&){return *this;} - -public: - /** - * Constructor - * Allocate the subleafs array - * @param inParent the SubOctree parent (0 if node) - * @param inSubOctreeHeight Height of this suboctree - * @param inSubOctreePosition Level of the current suboctree in the global tree (0 if upper tree) - */ - FSubOctree(FAbstractSubOctree<ParticleClass,CellClass,LeafClass>* const inParent, const long inIndexInParent, - const int inSubOctreeHeight, const int inSubOctreePosition) : - FAbstractSubOctree<ParticleClass,CellClass,LeafClass>(inParent, inIndexInParent, inSubOctreeHeight, inSubOctreePosition) { - - const long cellsAtLeafLevel = 1 << (3 * inSubOctreeHeight); - this->subleafs = new FAbstractSubOctree<ParticleClass,CellClass,LeafClass>*[cellsAtLeafLevel]; - assert(this->subleafs, "Allocation failled", __LINE__, __FILE__); - - for( int indexLeaf = 0 ; indexLeaf < cellsAtLeafLevel ; ++indexLeaf ){ - this->subleafs[indexLeaf] = 0; - } - } - - /** - * Destructor dealloc all suboctrees leafs & leafs array - */ - virtual ~FSubOctree(){ - const long cellsAtLeafLevel = 1 << (3 * this->subOctreeHeight); - for( int indexLeaf = 0 ; indexLeaf < cellsAtLeafLevel ; ++indexLeaf ){ - if(this->subleafs[indexLeaf]) delete this->subleafs[indexLeaf]; - } - delete [] this->subleafs; - } - - /** - * Refer to FAbstractSubOctree::insert - */ - void insert(const MortonIndex index, ParticleClass* const inParticle, const int inTreeHeight, const FReal* const inBoxWidthAtLevel){ - // We need the morton index at the bottom level of this sub octree - // so we remove the right side - const MortonIndex arrayIndex = FAbstractSubOctree<ParticleClass,CellClass,LeafClass>::getLeafIndex(index,inTreeHeight); - // Is there already a leaf? - if( !this->subleafs[arrayIndex] ){ - // We need to create leaf sub octree - const int nextSubOctreePosition = this->subOctreePosition + this->subOctreeHeight; - const int nextSubOctreeHeight = FMath::Min(inTreeHeight - nextSubOctreePosition, this->subOctreeHeight); - - // Next suboctree is a middle suboctree - if(inTreeHeight > nextSubOctreeHeight + nextSubOctreePosition){ - this->subleafs[arrayIndex] = new FSubOctree(this,arrayIndex,nextSubOctreeHeight,nextSubOctreePosition); - } - // Or next suboctree contains the reail leaf! - else{ - this->subleafs[arrayIndex] = new FSubOctreeWithLeafs<ParticleClass,CellClass,LeafClass>(this,arrayIndex,nextSubOctreeHeight,nextSubOctreePosition); - } - - // We need to inform parent class - FAbstractSubOctree<ParticleClass,CellClass,LeafClass>::newLeafInserted( arrayIndex, index >> (3 * (inTreeHeight-nextSubOctreePosition) ), inBoxWidthAtLevel); - } - // Ask next suboctree to insert the particle - this->subleafs[arrayIndex]->insert( index, inParticle, inTreeHeight, inBoxWidthAtLevel); - } - - /** To get access to leafs elements (child suboctree) - * @param index the position of the leaf/child suboctree - * @return child at this index */ - FAbstractSubOctree<ParticleClass,CellClass,LeafClass>* leafs(const int index) { - return this->subleafs[index]; - } - - /** To get access to leafs elements (child suboctree) - * @param index the position of the leaf/child suboctree - * @return child at this index */ - const FAbstractSubOctree<ParticleClass,CellClass,LeafClass>* leafs(const int index) const { - return this->subleafs[index]; - } -}; - - -#endif //FSUBOCTREE_HPP -// [--LICENSE--] diff --git a/Sources/Containers/FTreeCoordinate.hpp b/Sources/Containers/FTreeCoordinate.hpp deleted file mode 100644 index 232ce0963..000000000 --- a/Sources/Containers/FTreeCoordinate.hpp +++ /dev/null @@ -1,188 +0,0 @@ -#ifndef FTREECOORDINATE_HPP -#define FTREECOORDINATE_HPP -// /!\ Please, you must read the license at the bottom of this page - - -/** Morton index */ -typedef long long MortonIndex; - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FTreeCoordinate -* Please read the license -* -* This class represents tree coordinate. It is used to save -* the position in "box unit" (not system/space unit!). -* It is directly related to morton index -*/ -class FTreeCoordinate{ -private: - long x; //< x box-th position - long y; //< y box-th position - long z; //< z box-th position - -public: - /** Default constructor (position = {0,0,0})*/ - FTreeCoordinate() : x(0), y(0), z(0){ - } - - /** - * Default constructor - * @param inX the x - * @param inY the y - * @param inZ the z - */ - FTreeCoordinate(const long inX,const long inY,const long inZ) - : x(inX), y(inY), z(inZ){ - } - - /** Default destructor */ - virtual ~FTreeCoordinate(){ - } - - /** - * Copy constructor - * @param other the source class to copy - */ - FTreeCoordinate(const FTreeCoordinate& other):x(other.x), y(other.y), z(other.z){ - } - - /** - * Copy constructor - * @param other the source class to copy - * @return this a reference to the current object - */ - FTreeCoordinate& operator=(const FTreeCoordinate& other){ - this->x = other.x; - this->y = other.y; - this->z = other.z; - return *this; - } - - /** - * Position setter - * @param inX the new x - * @param inY the new y - * @param inZ the new z - */ - void setPosition(const long inX,const long inY,const long inZ){ - this->x = inX; - this->y = inY; - this->z = inZ; - } - - /** - * X Getter - * @return this->x - */ - long getX() const{ - return this->x; - } - - /** - * Y Getter - * @return this->y - */ - long getY() const{ - return this->y; - } - - /** - * Z Getter - * @return this->z - */ - long getZ() const{ - return this->z; - } - - /** - * X Setter, simply change x position - * @param the new x - */ - void setX(const long inX){ - this->x = inX; - } - - /** - * Y Setter, simply change y position - * @param the new y - */ - void setY(const long inY){ - this->y = inY; - } - - /** - * Z Setter, simply change z position - * @param the new z - */ - void setZ(const long inZ){ - this->z = inZ; - } - - /** - * To get the morton index of the current position - * @complexity inLevel - * @param inLevel the level of the component - * @return morton index - */ - MortonIndex getMortonIndex(const int inLevel) const{ - MortonIndex index = 0x0LL; - MortonIndex mask = 0x1LL; - // the ordre is xyz.xyz... - MortonIndex mx = this->x << 2; - MortonIndex my = this->y << 1; - MortonIndex mz = this->z; - - for(int indexLevel = 0; indexLevel < inLevel ; ++indexLevel){ - index |= (mz & mask); - mask <<= 1; - index |= (my & mask); - mask <<= 1; - index |= (mx & mask); - mask <<= 1; - - mz <<= 2; - my <<= 2; - mx <<= 2; - } - - return index; - } - - /** This function set the position of the current object using a morton index - * @param inIndex the morton index to compute position - * @param the level of the morton index - */ - void setPositionFromMorton(MortonIndex inIndex, const int inLevel){ - MortonIndex mask = 0x1LL; - - this->x = 0; - this->y = 0; - this->z = 0; - - for(int indexLevel = 0; indexLevel < inLevel ; ++indexLevel){ - z |= (inIndex & mask); - inIndex >>= 1; - y |= (inIndex & mask); - inIndex >>= 1; - x |= (inIndex & mask); - - mask <<= 1; - } - - } - - /** Test equal operator - * @param other the coordinate to compare - * @return true if other & current object have same position - */ - bool operator==(const FTreeCoordinate& other){ - return x == other.x && y == other.y && z == other.z; - } -}; - - - -#endif //FTREECOORDINATE_HPP - -// [--LICENSE--] diff --git a/Sources/Core/FFmmAlgorithm.hpp b/Sources/Core/FFmmAlgorithm.hpp deleted file mode 100644 index bbe1380ac..000000000 --- a/Sources/Core/FFmmAlgorithm.hpp +++ /dev/null @@ -1,237 +0,0 @@ -#ifndef FFMMALGORITHM_HPP -#define FFMMALGORITHM_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FAssertable.hpp" -#include "../Utils/FDebug.hpp" -#include "../Utils/FTrace.hpp" -#include "../Utils/FTic.hpp" - -#include "../Containers/FOctree.hpp" - - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmmAlgorithm -* @brief -* Please read the license -* -* This class is a basic FMM algorithm -* It just iterates on a tree and call the kernels with good arguments. -* -* Of course this class does not deallocate pointer given in arguements. -*/ -template<template< class ParticleClass, class CellClass, int OctreeHeight> class KernelClass, - class ParticleClass, class CellClass, - template<class ParticleClass> class LeafClass, - int OctreeHeight, int SubtreeHeight> -class FFmmAlgorithm : protected FAssertable{ - // To reduce the size of variable type based on foctree in this file - typedef FOctree<ParticleClass, CellClass, LeafClass, OctreeHeight, SubtreeHeight> Octree; - typedef typename FOctree<ParticleClass, CellClass,LeafClass, OctreeHeight, SubtreeHeight>::Iterator FOctreeIterator; - - Octree* const tree; //< The octree to work on - KernelClass<ParticleClass, CellClass, OctreeHeight>* const kernels; //< The kernels - - FDEBUG(FTic counterTime); //< In case of debug: to count the elapsed time - FDEBUG(FTic computationCounter); //< In case of debug: to count computation time - -public: - /** The constructor need the octree and the kernels used for computation - * @param inTree the octree to work on - * @param inKernels the kernels to call - * An assert is launched if one of the arguments is null - */ - FFmmAlgorithm(Octree* const inTree, KernelClass<ParticleClass,CellClass,OctreeHeight>* const inKernels) - : tree(inTree) , kernels(inKernels) { - - assert(tree, "tree cannot be null", __LINE__, __FILE__); - assert(kernels, "kernels cannot be null", __LINE__, __FILE__); - - FDEBUG(FDebug::Controller << "FFmmAlgorithm\n"); - } - - /** Default destructor */ - virtual ~FFmmAlgorithm(){ - } - - /** - * To execute the fmm algorithm - * Call this function to run the complete algorithm - */ - void execute(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - - kernels->init(); - - bottomPass(); - upwardPass(); - - downardPass(); - - directPass(); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** P2M */ - void bottomPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Bottom Pass\n").write(FDebug::Flush) ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - FOctreeIterator octreeIterator(tree); - - // Iterate on leafs - octreeIterator.gotoBottomLeft(); - do{ - // We need the current cell that represent the leaf - // and the list of particles - FDEBUG(computationCounter.tic()); - kernels->P2M( octreeIterator.getCurrentCell() , octreeIterator.getCurrentListSources()); - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } while(octreeIterator.moveRight()); - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** M2M */ - void upwardPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Upward Pass\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - // Start from leal level - 1 - FOctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - octreeIterator.moveUp(); - - FOctreeIterator avoidGotoLeftIterator(octreeIterator); - - // for each levels - for(int idxLevel = OctreeHeight - 2 ; idxLevel > 1 ; --idxLevel ){ - // for each cells - do{ - // We need the current cell and the child - // child is an array (of 8 child) that may be null - FDEBUG(computationCounter.tic()); - kernels->M2M( octreeIterator.getCurrentCell() , octreeIterator.getCurrentChild(), idxLevel); - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } while(octreeIterator.moveRight()); - - avoidGotoLeftIterator.moveUp(); - octreeIterator = avoidGotoLeftIterator;// equal octreeIterator.moveUp(); octreeIterator.gotoLeft(); - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** M2L L2L */ - void downardPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Downward Pass (M2L)\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - { // first M2L - FOctreeIterator octreeIterator(tree); - octreeIterator.moveDown(); - - FOctreeIterator avoidGotoLeftIterator(octreeIterator); - - CellClass* neighbors[208]; - // for each levels - for(int idxLevel = 2 ; idxLevel < OctreeHeight ; ++idxLevel ){ - // for each cells - do{ - FDEBUG(computationCounter.tic()); - const int counter = tree->getDistantNeighbors(neighbors, octreeIterator.getCurrentGlobalIndex(),idxLevel); - if(counter) kernels->M2L( octreeIterator.getCurrentCell() , neighbors, counter, idxLevel); - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } while(octreeIterator.moveRight()); - - avoidGotoLeftIterator.moveDown(); - octreeIterator = avoidGotoLeftIterator; - } - } - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - - FDEBUG( FDebug::Controller.write("\tStart Downward Pass (L2L)\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( totalComputation = 0 ); - { // second L2L - FOctreeIterator octreeIterator(tree); - octreeIterator.moveDown(); - - FOctreeIterator avoidGotoLeftIterator(octreeIterator); - - const int heightMinusOne = OctreeHeight - 1; - // for each levels exepted leaf level - for(int idxLevel = 2 ; idxLevel < heightMinusOne ; ++idxLevel ){ - // for each cells - do{ - FDEBUG(computationCounter.tic()); - kernels->L2L( octreeIterator.getCurrentCell() , octreeIterator.getCurrentChild(), idxLevel); - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } while(octreeIterator.moveRight()); - - avoidGotoLeftIterator.moveDown(); - octreeIterator = avoidGotoLeftIterator; - } - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** P2P */ - void directPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Direct Pass\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - const int heightMinusOne = OctreeHeight - 1; - - FOctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - // There is a maximum of 26 neighbors - FList<ParticleClass*>* neighbors[26]; - // for each leafs - do{ - FDEBUG(computationCounter.tic()); - kernels->L2P(octreeIterator.getCurrentCell(), octreeIterator.getCurrentListTargets()); - // need the current particles and neighbors particles - const int counter = tree->getLeafsNeighbors(neighbors, octreeIterator.getCurrentGlobalIndex(),heightMinusOne); - kernels->P2P( octreeIterator.getCurrentListTargets(), octreeIterator.getCurrentListSources() , neighbors, counter); - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } while(octreeIterator.moveRight()); - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - -}; - - -#endif //FFMMALGORITHM_HPP - -// [--LICENSE--] diff --git a/Sources/Core/FFmmAlgorithmThread.hpp b/Sources/Core/FFmmAlgorithmThread.hpp deleted file mode 100644 index 0f35610cd..000000000 --- a/Sources/Core/FFmmAlgorithmThread.hpp +++ /dev/null @@ -1,352 +0,0 @@ -#ifndef FFMMALGORITHMTHREAD_HPP -#define FFMMALGORITHMTHREAD_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FAssertable.hpp" -#include "../Utils/FDebug.hpp" -#include "../Utils/FTrace.hpp" -#include "../Utils/FTic.hpp" -#include "../Utils/FGlobal.hpp" - -#include "../Containers/FOctree.hpp" - - -#include <omp.h> - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmmAlgorithmThread -* @brief -* Please read the license -* -* This class is a threaded FMM algorithm -* It just iterates on a tree and call the kernels with good arguments. -* It used the inspector-executor model : -* iterates on the tree and builds an array to work in parallel on this array -* -* Of course this class does not deallocate pointer given in arguements. -* -* Threaded & based on the inspector-executor model -* schedule(runtime) -*/ -template<template< class ParticleClass, class CellClass, int OctreeHeight> class KernelClass, - class ParticleClass, class CellClass, - template<class ParticleClass> class LeafClass, - int OctreeHeight, int SubtreeHeight> -class FFmmAlgorithmThread : protected FAssertable{ - // To reduce the size of variable type based on foctree in this file - typedef FOctree<ParticleClass, CellClass, LeafClass, OctreeHeight, SubtreeHeight> Octree; - typedef typename FOctree<ParticleClass, CellClass,LeafClass, OctreeHeight, SubtreeHeight>::Iterator OctreeIterator; - typedef KernelClass<ParticleClass, CellClass, OctreeHeight> Kernel; - - Octree* const tree; //< The octree to work on - Kernel* kernels[FThreadNumbers]; //< The kernels - - FDEBUG(FTic counterTime); //< In case of debug: to count the elapsed time - FDEBUG(FTic computationCounter); //< In case of debug: to count computation time - - OctreeIterator* iterArray; - - static const int SizeShape = 3*3*3; - int shapeLeaf[SizeShape]; - -public: - /** The constructor need the octree and the kernels used for computation - * @param inTree the octree to work on - * @param inKernels the kernels to call - * An assert is launched if one of the arguments is null - */ - FFmmAlgorithmThread(Octree* const inTree, Kernel* const inKernels) - : tree(inTree) , iterArray(0) { - - assert(tree, "tree cannot be null", __LINE__, __FILE__); - assert(kernels, "kernels cannot be null", __LINE__, __FILE__); - - for(int idxThread = 0 ; idxThread < FThreadNumbers ; ++idxThread){ - this->kernels[idxThread] = new KernelClass<ParticleClass, CellClass, OctreeHeight>(*inKernels); - } - - FDEBUG(FDebug::Controller << "FFmmAlgorithmThread\n"); - } - - /** Default destructor */ - virtual ~FFmmAlgorithmThread(){ - for(int idxThread = 0 ; idxThread < FThreadNumbers ; ++idxThread){ - delete this->kernels[idxThread]; - } - } - - /** - * To execute the fmm algorithm - * Call this function to run the complete algorithm - */ - void execute(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - - for(int idxShape = 0 ; idxShape < SizeShape ; ++idxShape){ - this->shapeLeaf[idxShape] = 0; - } - const int LeafIndex = OctreeHeight - 1; - - // Count leaf - int leafs = 0; - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - do{ - ++leafs; - const MortonIndex index = octreeIterator.getCurrentGlobalIndex(); - FTreeCoordinate coord; - coord.setPositionFromMorton(index, LeafIndex); - ++this->shapeLeaf[(coord.getX()%3)*9 + (coord.getY()%3)*3 + (coord.getZ()%3)]; - - } while(octreeIterator.moveRight()); - iterArray = new OctreeIterator[leafs]; - assert(iterArray, "iterArray bad alloc", __LINE__, __FILE__); - - for(int idxThread = 0 ; idxThread < FThreadNumbers ; ++idxThread){ - this->kernels[idxThread]->init(); - } - - bottomPass(); - upwardPass(); - - downardPass(); - - directPass(); - - delete [] iterArray; - iterArray = 0; - - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** P2M */ - void bottomPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Bottom Pass\n").write(FDebug::Flush) ); - FDEBUG( counterTime.tic() ); - - OctreeIterator octreeIterator(tree); - int leafs = 0; - // Iterate on leafs - octreeIterator.gotoBottomLeft(); - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - // We need the current cell that represent the leaf - // and the list of particles - myThreadkernels->P2M( iterArray[idxLeafs].getCurrentCell() , iterArray[idxLeafs].getCurrentListSources()); - } - } - FDEBUG(computationCounter.tac()); - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << computationCounter.elapsed() << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** M2M */ - void upwardPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Upward Pass\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - // Start from leal level - 1 - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - octreeIterator.moveUp(); - OctreeIterator avoidGotoLeftIterator(octreeIterator); - - // for each levels - for(int idxLevel = OctreeHeight - 2 ; idxLevel > 1 ; --idxLevel ){ - int leafs = 0; - // for each cells - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - avoidGotoLeftIterator.moveUp(); - octreeIterator = avoidGotoLeftIterator;// equal octreeIterator.moveUp(); octreeIterator.gotoLeft(); - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - // We need the current cell and the child - // child is an array (of 8 child) that may be null - myThreadkernels->M2M( iterArray[idxLeafs].getCurrentCell() , iterArray[idxLeafs].getCurrentChild(), idxLevel); - } - } - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** M2L L2L */ - void downardPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Downward Pass (M2L)\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - { // first M2L - OctreeIterator octreeIterator(tree); - octreeIterator.moveDown(); - OctreeIterator avoidGotoLeftIterator(octreeIterator); - - // for each levels - for(int idxLevel = 2 ; idxLevel < OctreeHeight ; ++idxLevel ){ - int leafs = 0; - // for each cells - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - avoidGotoLeftIterator.moveDown(); - octreeIterator = avoidGotoLeftIterator; - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - CellClass* neighbors[208]; - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - const int counter = tree->getDistantNeighbors(neighbors, iterArray[idxLeafs].getCurrentGlobalIndex(),idxLevel); - if(counter) myThreadkernels->M2L( iterArray[idxLeafs].getCurrentCell() , neighbors, counter, idxLevel); - } - } - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } - } - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - - FDEBUG( FDebug::Controller.write("\tStart Downward Pass (L2L)\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( totalComputation = 0 ); - { // second L2L - OctreeIterator octreeIterator(tree); - octreeIterator.moveDown(); - - OctreeIterator avoidGotoLeftIterator(octreeIterator); - - const int heightMinusOne = OctreeHeight - 1; - // for each levels exepted leaf level - for(int idxLevel = 2 ; idxLevel < heightMinusOne ; ++idxLevel ){ - int leafs = 0; - // for each cells - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - avoidGotoLeftIterator.moveDown(); - octreeIterator = avoidGotoLeftIterator; - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - myThreadkernels->L2L( iterArray[idxLeafs].getCurrentCell() , iterArray[idxLeafs].getCurrentChild(), idxLevel); - } - } - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** P2P */ - void directPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Direct Pass\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - - OctreeIterator* shapeArray[SizeShape]; - int countShape[SizeShape]; - for(int idxShape = 0 ; idxShape < SizeShape ; ++idxShape){ - shapeArray[idxShape] = new OctreeIterator[this->shapeLeaf[idxShape]]; - countShape[idxShape] = 0; - } - - const int LeafIndex = OctreeHeight - 1; - //int leafs = 0; - { - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - // for each leafs - do{ - //iterArray[leafs] = octreeIterator; - //++leafs; - const MortonIndex index = octreeIterator.getCurrentGlobalIndex(); - FTreeCoordinate coord; - coord.setPositionFromMorton(index, LeafIndex); - const int shapePosition = (coord.getX()%3)*9 + (coord.getY()%3)*3 + (coord.getZ()%3); - shapeArray[shapePosition][countShape[shapePosition]] = octreeIterator; - ++countShape[shapePosition]; - - } while(octreeIterator.moveRight()); - } - - FDEBUG(computationCounter.tic()); - for(int idxShape = 0 ; idxShape < SizeShape ; ++idxShape){ - const int leafAtThisShape = this->shapeLeaf[idxShape]; - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - // There is a maximum of 26 neighbors - FList<ParticleClass*>* neighbors[26]; - - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafAtThisShape ; ++idxLeafs){ - myThreadkernels->L2P(shapeArray[idxShape][idxLeafs].getCurrentCell(), shapeArray[idxShape][idxLeafs].getCurrentListTargets()); - // need the current particles and neighbors particles - const int counter = tree->getLeafsNeighbors(neighbors, shapeArray[idxShape][idxLeafs].getCurrentGlobalIndex(),LeafIndex); - myThreadkernels->P2P( shapeArray[idxShape][idxLeafs].getCurrentListTargets(), shapeArray[idxShape][idxLeafs].getCurrentListSources() , neighbors, counter); - } - } - } - FDEBUG(computationCounter.tac()); - - for(int idxShape = 0 ; idxShape < SizeShape ; ++idxShape){ - delete [] shapeArray[idxShape]; - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << computationCounter.elapsed() << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - -}; - - -#endif //FFMMALGORITHMTHREAD_HPP - -// [--LICENSE--] diff --git a/Sources/Core/FFmmAlgorithmThreadProc.hpp b/Sources/Core/FFmmAlgorithmThreadProc.hpp deleted file mode 100644 index 565f31ba8..000000000 --- a/Sources/Core/FFmmAlgorithmThreadProc.hpp +++ /dev/null @@ -1,572 +0,0 @@ -#ifndef FFMMALGORITHMTHREADPROC_HPP -#define FFMMALGORITHMTHREADPROC_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FAssertable.hpp" -#include "../Utils/FDebug.hpp" -#include "../Utils/FTrace.hpp" -#include "../Utils/FTic.hpp" -#include "../Utils/FGlobal.hpp" - -#include "../Containers/FOctree.hpp" - - -//================================================================================================ -#ifdef FUSE_MPI -// Compile by mpic++ testApplication.cpp ../Utils/FAssertable.cpp -o testApplication.exe -// run by mpirun -np 4 ./testApplication.exe -#include "../Utils/FMpiApplication.hpp" -typedef FMpiApplication ApplicationImplementation; -#else -// Compile by g++ testApplication.cpp ../Utils/FAssertable.cpp -o testApplication.exe -#include "../Utils/FSingleApplication.hpp" -typedef FSingleApplication ApplicationImplementation; -#endif -//================================================================================================ - -#include <omp.h> - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmmAlgorithmThreadProc -* @brief -* Please read the license -* -* This class is a threaded FMM algorithm -* It just iterates on a tree and call the kernels with good arguments. -* It used the inspector-executor model : -* iterates on the tree and builds an array to work in parallel on this array -* -* Of course this class does not deallocate pointer given in arguements. -* -* Threaded & based on the inspector-executor model -* schedule(runtime) -*/ -template<template< class ParticleClass, class CellClass, int OctreeHeight> class KernelClass, - class ParticleClass, class CellClass, - template<class ParticleClass> class LeafClass, - int OctreeHeight, int SubtreeHeight> -class FFmmAlgorithmThreadProc : protected FAssertable, protected ApplicationImplementation{ - // To reduce the size of variable type based on foctree in this file - typedef FOctree<ParticleClass, CellClass, LeafClass, OctreeHeight, SubtreeHeight> Octree; - typedef typename FOctree<ParticleClass, CellClass,LeafClass, OctreeHeight, SubtreeHeight>::Iterator OctreeIterator; - typedef KernelClass<ParticleClass, CellClass, OctreeHeight> Kernel; - - Octree* const tree; //< The octree to work on - Kernel* kernels[FThreadNumbers]; //< The kernels - - FDEBUG(FTic counterTime); //< In case of debug: to count the elapsed time - FDEBUG(FTic computationCounter); //< In case of debug: to count computation time - - OctreeIterator* iterArray; - - static const int SizeShape = 3*3*3; - int shapeLeaf[SizeShape]; - - void run(){} - -public: - /** The constructor need the octree and the kernels used for computation - * @param inTree the octree to work on - * @param inKernels the kernels to call - * An assert is launched if one of the arguments is null - */ - FFmmAlgorithmThreadProc(Octree* const inTree, Kernel* const inKernels, const int inArgc, char ** const inArgv ) - : ApplicationImplementation(inArgc,inArgv), tree(inTree) , iterArray(0) { - - assert(tree, "tree cannot be null", __LINE__, __FILE__); - assert(kernels, "kernels cannot be null", __LINE__, __FILE__); - - for(int idxThread = 0 ; idxThread < FThreadNumbers ; ++idxThread){ - this->kernels[idxThread] = new KernelClass<ParticleClass, CellClass, OctreeHeight>(*inKernels); - } - - FDEBUG(FDebug::Controller << "FFmmAlgorithmThreadProc\n"); - } - - /** Default destructor */ - virtual ~FFmmAlgorithmThreadProc(){ - for(int idxThread = 0 ; idxThread < FThreadNumbers ; ++idxThread){ - delete this->kernels[idxThread]; - } - } - - /** - * To execute the fmm algorithm - * Call this function to run the complete algorithm - */ - void execute(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - - for(int idxShape = 0 ; idxShape < SizeShape ; ++idxShape){ - this->shapeLeaf[idxShape] = 0; - } - const int LeafIndex = OctreeHeight - 1; - - // Count leaf - int leafs = 0; - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - do{ - ++leafs; - const MortonIndex index = octreeIterator.getCurrentGlobalIndex(); - FTreeCoordinate coord; - coord.setPositionFromMorton(index, LeafIndex); - ++this->shapeLeaf[(coord.getX()%3)*9 + (coord.getY()%3)*3 + (coord.getZ()%3)]; - - } while(octreeIterator.moveRight()); - iterArray = new OctreeIterator[leafs]; - assert(iterArray, "iterArray bad alloc", __LINE__, __FILE__); - - for(int idxThread = 0 ; idxThread < FThreadNumbers ; ++idxThread){ - this->kernels[idxThread]->init(); - } - - bottomPass(); - upwardPass(); - - downardPass(); - - directPass(); - - delete [] iterArray; - iterArray = 0; - - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** P2M */ - void bottomPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Bottom Pass\n").write(FDebug::Flush) ); - FDEBUG( counterTime.tic() ); - - OctreeIterator octreeIterator(tree); - const int nbProcess = processCount(); - const int idPorcess = processId(); - int leafs = 0; - // Iterate on leafs - octreeIterator.gotoBottomLeft(); - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - - const float stepIdx = float(leafs) / nbProcess; - const int startIdx = idPorcess*stepIdx; - const int endIdx = (idPorcess+1)*stepIdx; - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - #pragma omp for - for(int idxLeafs = startIdx ; idxLeafs < endIdx ; ++idxLeafs){ - // We need the current cell that represent the leaf - // and the list of particles - myThreadkernels->P2M( iterArray[idxLeafs].getCurrentCell() , iterArray[idxLeafs].getCurrentListSources()); - } - - #pragma omp single nowait - { - for(int idxLeafs = startIdx ; idxLeafs < endIdx ; ++idxLeafs){ - for(int idxProc = 0 ; idxProc < nbProcess ; ++idxProc){ - if(idxProc != idPorcess){ - sendData(idxProc,sizeof(CellClass),iterArray[idxLeafs].getCurrentCell(),idxLeafs); - } - } - } - } - - #pragma omp single nowait - { - int needToReceive = leafs - (endIdx-startIdx); - CellClass tempCell; - int source = 0, tag = 0, filled = 0; - - while(needToReceive){ - receiveData(sizeof(CellClass),&tempCell,&source,&tag,&filled); - if(filled){ - *iterArray[tag].getCurrentCell() = tempCell; - } - --needToReceive; - } - } - } - FDEBUG(computationCounter.tac()); - - processBarrier(); - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << computationCounter.elapsed() << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** M2M */ - void upwardPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Upward Pass\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - // Start from leal level - 1 - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - octreeIterator.moveUp(); - OctreeIterator avoidGotoLeftIterator(octreeIterator); - - const int nbProcess = processCount(); - const int idPorcess = processId(); - - // for each levels - for(int idxLevel = OctreeHeight - 2 ; idxLevel > 1 ; --idxLevel ){ - int leafs = 0; - // for each cells - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - avoidGotoLeftIterator.moveUp(); - octreeIterator = avoidGotoLeftIterator;// equal octreeIterator.moveUp(); octreeIterator.gotoLeft(); - - - const float stepIdx = float(leafs) / nbProcess; - const int startIdx = idPorcess*stepIdx; - const int endIdx = (idPorcess+1)*stepIdx; - - FDEBUG(computationCounter.tic()); - - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - #pragma omp for - for(int idxLeafs = startIdx ; idxLeafs < endIdx ; ++idxLeafs){ - myThreadkernels->M2M( iterArray[idxLeafs].getCurrentCell() , iterArray[idxLeafs].getCurrentChild(), idxLevel); - } - - #pragma omp single nowait - { - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } - - // send computed data - #pragma omp single nowait - { - for(int idxLeafs = startIdx ; idxLeafs < endIdx ; ++idxLeafs){ - for(int idxProc = 0 ; idxProc < nbProcess ; ++idxProc){ - if(idxProc != idPorcess){ - sendData(idxProc,sizeof(CellClass),iterArray[idxLeafs].getCurrentCell(),idxLeafs); - } - } - } - } - - // received computed data - #pragma omp single nowait - { - int needToReceive = leafs - (endIdx-startIdx); - CellClass tempCell; - int source = 0, tag = 0, filled = 0; - - while(needToReceive){ - receiveData(sizeof(CellClass),&tempCell,&source,&tag,&filled); - if(filled){ - *iterArray[tag].getCurrentCell() = tempCell; - } - --needToReceive; - } - } - } - processBarrier(); - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** M2L L2L */ - void downardPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Downward Pass (M2L)\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - { // first M2L - OctreeIterator octreeIterator(tree); - octreeIterator.moveDown(); - OctreeIterator avoidGotoLeftIterator(octreeIterator); - - const int nbProcess = processCount(); - const int idPorcess = processId(); - - - // for each levels - for(int idxLevel = 2 ; idxLevel < OctreeHeight ; ++idxLevel ){ - int leafs = 0; - // for each cells - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - avoidGotoLeftIterator.moveDown(); - octreeIterator = avoidGotoLeftIterator; - - const float stepIdx = float(leafs) / nbProcess; - const int startIdx = idPorcess*stepIdx; - const int endIdx = (idPorcess+1)*stepIdx; - - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - CellClass* neighbors[208]; - - #pragma omp for - for(int idxLeafs = startIdx ; idxLeafs < endIdx ; ++idxLeafs){ - const int counter = tree->getDistantNeighbors(neighbors, iterArray[idxLeafs].getCurrentGlobalIndex(),idxLevel); - if(counter) myThreadkernels->M2L( iterArray[idxLeafs].getCurrentCell() , neighbors, counter, idxLevel); - } - - #pragma omp single nowait - { - for(int idxLeafs = startIdx ; idxLeafs < endIdx ; ++idxLeafs){ - for(int idxProc = 0 ; idxProc < nbProcess ; ++idxProc){ - if(idxProc != idPorcess){ - sendData(idxProc,sizeof(CellClass),iterArray[idxLeafs].getCurrentCell(),idxLeafs); - } - } - } - } - - // received computed data - #pragma omp single nowait - { - int needToReceive = leafs - (endIdx-startIdx); - CellClass tempCell; - int source = 0, tag = 0, filled = 0; - - while(needToReceive){ - receiveData(sizeof(CellClass),&tempCell,&source,&tag,&filled); - if(filled){ - *iterArray[tag].getCurrentCell() = tempCell; - } - --needToReceive; - } - } - } - processBarrier(); - } - } - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - - FDEBUG( FDebug::Controller.write("\tStart Downward Pass (L2L)\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( totalComputation = 0 ); - { // second L2L - OctreeIterator octreeIterator(tree); - octreeIterator.moveDown(); - - OctreeIterator avoidGotoLeftIterator(octreeIterator); - - const int heightMinusOne = OctreeHeight - 1; - const int nbProcess = processCount(); - const int idPorcess = processId(); - - // for each levels exepted leaf level - for(int idxLevel = 2 ; idxLevel < heightMinusOne ; ++idxLevel ){ - int leafs = 0; - // for each cells - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - avoidGotoLeftIterator.moveDown(); - octreeIterator = avoidGotoLeftIterator; - - const float stepIdx = float(leafs) / nbProcess; - const int startIdx = idPorcess*stepIdx; - const int endIdx = (idPorcess+1)*stepIdx; - - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - #pragma omp for - for(int idxLeafs = startIdx ; idxLeafs < endIdx ; ++idxLeafs){ - myThreadkernels->L2L( iterArray[idxLeafs].getCurrentCell() , iterArray[idxLeafs].getCurrentChild(), idxLevel); - } - - #pragma omp single nowait - { - const int sizeBuffer = 8 * sizeof(CellClass); - char buffer[sizeBuffer]; - for(int idxLeafs = startIdx ; idxLeafs < endIdx ; ++idxLeafs){ - int position=0; - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - if(iterArray[idxLeafs].getCurrentChild()[idxChild]){ - memcpy(&buffer[position*sizeof(CellClass)],iterArray[idxLeafs].getCurrentChild()[idxChild],sizeof(CellClass)); - ++position; - } - } - - for(int idxProc = 0 ; idxProc < nbProcess ; ++idxProc){ - if(idxProc != idPorcess){ - sendData(idxProc,position*sizeof(CellClass),buffer,idxLeafs); - } - } - } - } - - // received computed data - #pragma omp single nowait - { - int needToReceive = leafs - (endIdx-startIdx); - int source = 0, tag = 0, filled = 0; - const int sizeBuffer = 8 * sizeof(CellClass); - char buffer[sizeBuffer]; - - while(needToReceive){ - receiveData(sizeBuffer,buffer,&source,&tag,&filled); - if(filled){ - int position = 0; - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - if(iterArray[tag].getCurrentChild()[idxChild]){ - memcpy(iterArray[tag].getCurrentChild()[idxChild],&buffer[position*sizeof(CellClass)],sizeof(CellClass)); - ++position; - } - } - } - --needToReceive; - } - } - } - processBarrier(); - } - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** P2P */ - void directPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Direct Pass\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - - const int LeafIndex = OctreeHeight - 1; - int leafs = 0; - { - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - // for each leafs - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - } - - FDEBUG(computationCounter.tic()); - - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - // There is a maximum of 26 neighbors - FList<ParticleClass*>* neighbors[26]; - - const float stepIdx = float(leafs) / processCount(); - const int startIdx = processId()*stepIdx; - const int endIdx = (processId()+1)*stepIdx; - - #pragma omp for - for(int idxLeafs = startIdx ; idxLeafs < endIdx ; ++idxLeafs){ - myThreadkernels->L2P(iterArray[idxLeafs].getCurrentCell(), iterArray[idxLeafs].getCurrentListTargets()); - // need the current particles and neighbors particles - const int counter = tree->getLeafsNeighbors(neighbors, iterArray[idxLeafs].getCurrentGlobalIndex(),LeafIndex); - myThreadkernels->P2P( iterArray[idxLeafs].getCurrentListTargets(), iterArray[idxLeafs].getCurrentListSources() , neighbors, counter); - } - } - FDEBUG(computationCounter.tac()); - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << computationCounter.elapsed() << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** This function test the octree to be sure that the fmm algorithm - * has worked completly. - */ - void ValidateFMMAlgoProc(){ - std::cout << "Check Result\n"; - int NbPart = 0; - int NbLeafs = 0; - { // Check that each particle has been summed with all other - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - do{ - NbPart += octreeIterator.getCurrentListSources()->getSize(); - ++NbLeafs; - } while(octreeIterator.moveRight()); - } - { - const float stepIdx = float(NbLeafs) / processCount(); - const int startIdx = processId()*stepIdx; - const int endIdx = (processId()+1)*stepIdx; - // Check that each particle has been summed with all other - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - - for(int idx = 0 ; idx < startIdx ; ++idx){ - octreeIterator.moveRight(); - } - - for(int idx = startIdx ; idx < endIdx ; ++idx){ - typename FList<ParticleClass*>::BasicIterator iter(*octreeIterator.getCurrentListTargets()); - - const bool isUsingTsm = (octreeIterator.getCurrentListTargets() != octreeIterator.getCurrentListSources()); - - while( iter.isValide() ){ - // If a particles has been impacted by less than NbPart - 1 (the current particle) - // there is a problem - if( (!isUsingTsm && iter.value()->getDataDown() != NbPart - 1) || - (isUsingTsm && iter.value()->getDataDown() != NbPart) ){ - std::cout << "Problem L2P + P2P, value on particle is : " << iter.value()->getDataDown() << "\n"; - } - iter.progress(); - } - octreeIterator.moveRight(); - } - } - - std::cout << "Done\n"; - } - - void print(){ - OctreeIterator octreeIterator(tree); - for(int idxLevel = OctreeHeight - 1 ; idxLevel > 1 ; --idxLevel ){ - do{ - std::cout << "[" << octreeIterator.getCurrentGlobalIndex() << "] up:" << octreeIterator.getCurrentCell()->getDataUp() << " down:" << octreeIterator.getCurrentCell()->getDataDown() << "\t"; - } while(octreeIterator.moveRight()); - std::cout << "\n"; - octreeIterator.gotoLeft(); - octreeIterator.moveDown(); - } - } - -}; - - - - - - -#endif //FFMMALGORITHMTHREAD_HPP - -// [--LICENSE--] diff --git a/Sources/Core/FFmmAlgorithmThreadTsm.hpp b/Sources/Core/FFmmAlgorithmThreadTsm.hpp deleted file mode 100644 index c420048f8..000000000 --- a/Sources/Core/FFmmAlgorithmThreadTsm.hpp +++ /dev/null @@ -1,367 +0,0 @@ -#ifndef FFMMALGORITHMTHREADTSM_HPP -#define FFMMALGORITHMTHREADTSM_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FAssertable.hpp" -#include "../Utils/FDebug.hpp" -#include "../Utils/FTrace.hpp" -#include "../Utils/FTic.hpp" -#include "../Utils/FGlobal.hpp" - -#include "../Containers/FOctree.hpp" - - -#include <omp.h> - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmmAlgorithmThreadTsm -* @brief -* Please read the license -* -* This class is a threaded FMM algorithm -* It just iterates on a tree and call the kernels with good arguments. -* It used the inspector-executor model : -* iterates on the tree and builds an array to work in parallel on this array -* -* Of course this class does not deallocate pointer given in arguements. -* -* Threaded & based on the inspector-executor model -* schedule(runtime) -*/ -template<template< class ParticleClass, class CellClass, int OctreeHeight> class KernelClass, - class ParticleClass, class CellClass, - template<class ParticleClass> class LeafClass, - int OctreeHeight, int SubtreeHeight> -class FFmmAlgorithmThreadTsm : protected FAssertable{ - // To reduce the size of variable type based on foctree in this file - typedef FOctree<ParticleClass, CellClass, LeafClass, OctreeHeight, SubtreeHeight> Octree; - typedef typename FOctree<ParticleClass, CellClass,LeafClass, OctreeHeight, SubtreeHeight>::Iterator OctreeIterator; - typedef KernelClass<ParticleClass, CellClass, OctreeHeight> Kernel; - - Octree* const tree; //< The octree to work on - Kernel* kernels[FThreadNumbers]; //< The kernels - - FDEBUG(FTic counterTime); //< In case of debug: to count the elapsed time - FDEBUG(FTic computationCounter); //< In case of debug: to count computation time - - OctreeIterator* iterArray; - -public: - /** The constructor need the octree and the kernels used for computation - * @param inTree the octree to work on - * @param inKernels the kernels to call - * An assert is launched if one of the arguments is null - */ - FFmmAlgorithmThreadTsm(Octree* const inTree, Kernel* const inKernels) - : tree(inTree) , iterArray(0) { - - assert(tree, "tree cannot be null", __LINE__, __FILE__); - assert(kernels, "kernels cannot be null", __LINE__, __FILE__); - - for(int idxThread = 0 ; idxThread < FThreadNumbers ; ++idxThread){ - this->kernels[idxThread] = new KernelClass<ParticleClass, CellClass, OctreeHeight>(*inKernels); - } - - FDEBUG(FDebug::Controller << "FFmmAlgorithmThreadTsm\n"); - } - - /** Default destructor */ - virtual ~FFmmAlgorithmThreadTsm(){ - for(int idxThread = 0 ; idxThread < FThreadNumbers ; ++idxThread){ - delete this->kernels[idxThread]; - } - } - - /** - * To execute the fmm algorithm - * Call this function to run the complete algorithm - */ - void execute(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - - // Count leaf - int leafs = 0; - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - do{ - ++leafs; - } while(octreeIterator.moveRight()); - iterArray = new OctreeIterator[leafs]; - assert(iterArray, "iterArray bad alloc", __LINE__, __FILE__); - - for(int idxThread = 0 ; idxThread < FThreadNumbers ; ++idxThread){ - this->kernels[idxThread]->init(); - } - - bottomPass(); - upwardPass(); - - downardPass(); - - directPass(); - - delete [] iterArray; - iterArray = 0; - - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** P2M */ - void bottomPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Bottom Pass\n").write(FDebug::Flush) ); - FDEBUG( counterTime.tic() ); - - OctreeIterator octreeIterator(tree); - int leafs = 0; - // Iterate on leafs - octreeIterator.gotoBottomLeft(); - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - // We need the current cell that represent the leaf - // and the list of particles - FList<ParticleClass*>* const sources = iterArray[idxLeafs].getCurrentListSources(); - if(sources->getSize()){ - iterArray[idxLeafs].getCurrentCell()->setSourcesChildTrue(); - myThreadkernels->P2M( iterArray[idxLeafs].getCurrentCell() , sources); - } - if(iterArray[idxLeafs].getCurrentListTargets()->getSize()){ - iterArray[idxLeafs].getCurrentCell()->setTargetsChildTrue(); - } - } - } - FDEBUG(computationCounter.tac()); - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << computationCounter.elapsed() << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** M2M */ - void upwardPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Upward Pass\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - // Start from leal level - 1 - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - octreeIterator.moveUp(); - OctreeIterator avoidGotoLeftIterator(octreeIterator); - - // for each levels - for(int idxLevel = OctreeHeight - 2 ; idxLevel > 1 ; --idxLevel ){ - int leafs = 0; - // for each cells - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - avoidGotoLeftIterator.moveUp(); - octreeIterator = avoidGotoLeftIterator;// equal octreeIterator.moveUp(); octreeIterator.gotoLeft(); - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - // We need the current cell and the child - // child is an array (of 8 child) that may be null - CellClass* potentialChild[8]; - CellClass** const realChild = iterArray[idxLeafs].getCurrentChild(); - CellClass* const currentCell = iterArray[idxLeafs].getCurrentCell(); - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - potentialChild[idxChild] = 0; - if(realChild[idxChild]){ - if(realChild[idxChild]->hasSourcesChild()){ - currentCell->setSourcesChildTrue(); - potentialChild[idxChild] = realChild[idxChild]; - } - if(realChild[idxChild]->hasTargetsChild()){ - currentCell->setTargetsChildTrue(); - } - } - } - myThreadkernels->M2M( currentCell , potentialChild, idxLevel); - } - } - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** M2L L2L */ - void downardPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Downward Pass (M2L)\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - { // first M2L - OctreeIterator octreeIterator(tree); - octreeIterator.moveDown(); - OctreeIterator avoidGotoLeftIterator(octreeIterator); - - // for each levels - for(int idxLevel = 2 ; idxLevel < OctreeHeight ; ++idxLevel ){ - int leafs = 0; - // for each cells - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - avoidGotoLeftIterator.moveDown(); - octreeIterator = avoidGotoLeftIterator; - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - CellClass* neighbors[208]; - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - CellClass* const currentCell = iterArray[idxLeafs].getCurrentCell(); - if(currentCell->hasTargetsChild()){ - const int counter = tree->getDistantNeighbors(neighbors, iterArray[idxLeafs].getCurrentGlobalIndex(),idxLevel); - int offsetTargetNeighbors = 0; - for(int idxRealNeighbors = 0 ; idxRealNeighbors < counter ; ++idxRealNeighbors, ++offsetTargetNeighbors){ - if(neighbors[idxRealNeighbors]->hasSourcesChild()){ - if(idxRealNeighbors != offsetTargetNeighbors){ - neighbors[offsetTargetNeighbors] = neighbors[idxRealNeighbors]; - } - } - else{ - --offsetTargetNeighbors; - } - } - if(offsetTargetNeighbors){ - myThreadkernels->M2L( currentCell , neighbors, offsetTargetNeighbors, idxLevel); - } - } - } - } - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } - } - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - - FDEBUG( FDebug::Controller.write("\tStart Downward Pass (L2L)\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( totalComputation = 0 ); - { // second L2L - OctreeIterator octreeIterator(tree); - octreeIterator.moveDown(); - - OctreeIterator avoidGotoLeftIterator(octreeIterator); - - const int heightMinusOne = OctreeHeight - 1; - // for each levels exepted leaf level - for(int idxLevel = 2 ; idxLevel < heightMinusOne ; ++idxLevel ){ - int leafs = 0; - // for each cells - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - avoidGotoLeftIterator.moveDown(); - octreeIterator = avoidGotoLeftIterator; - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - CellClass* potentialChild[8]; - CellClass** const realChild = iterArray[idxLeafs].getCurrentChild(); - CellClass* const currentCell = iterArray[idxLeafs].getCurrentCell(); - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - if(realChild[idxChild] && realChild[idxChild]->hasTargetsChild()){ - potentialChild[idxChild] = realChild[idxChild]; - } - else{ - potentialChild[idxChild] = 0; - } - } - myThreadkernels->L2L( currentCell , potentialChild, idxLevel); - } - } - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** P2P */ - void directPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Direct Pass\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - - int leafs = 0; - { - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - // for each leafs - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - } - - const int heightMinusOne = OctreeHeight - 1; - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - // There is a maximum of 26 neighbors - FList<ParticleClass*>* neighbors[26]; - - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - myThreadkernels->L2P(iterArray[idxLeafs].getCurrentCell(), iterArray[idxLeafs].getCurrentListTargets()); - // need the current particles and neighbors particles - const int counter = tree->getLeafsNeighbors(neighbors, iterArray[idxLeafs].getCurrentGlobalIndex(),heightMinusOne); - myThreadkernels->P2P( iterArray[idxLeafs].getCurrentListTargets(), iterArray[idxLeafs].getCurrentListSources() , neighbors, counter); - } - } - FDEBUG(computationCounter.tac()); - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << computationCounter.elapsed() << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - -}; - - -#endif //FFMMALGORITHMTHREADTSM_HPP - -// [--LICENSE--] diff --git a/Sources/Core/FFmmAlgorithmThreadUs.hpp b/Sources/Core/FFmmAlgorithmThreadUs.hpp deleted file mode 100644 index cc0d6dac9..000000000 --- a/Sources/Core/FFmmAlgorithmThreadUs.hpp +++ /dev/null @@ -1,318 +0,0 @@ -#ifndef FFMMALGORITHMTHREADUS_HPP -#define FFMMALGORITHMTHREADUS_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FAssertable.hpp" -#include "../Utils/FDebug.hpp" -#include "../Utils/FTrace.hpp" -#include "../Utils/FTic.hpp" -#include "../Utils/FGlobal.hpp" - -#include "../Containers/FOctree.hpp" - - -#include <omp.h> - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmmAlgorithmThreadUs -* @brief -* Please read the license -* -* This class is a threaded FMM algorithm -* It just iterates on a tree and call the kernels with good arguments. -* It used the inspector-executor model : -* iterates on the tree and builds an array to work in parallel on this array -* -* Of course this class does not deallocate pointer given in arguements. -* -* Threaded & based on the inspector-executor model -* schedule(runtime) -*/ -template<template< class ParticleClass, class CellClass, int OctreeHeight> class KernelClass, - class ParticleClass, class CellClass, - template<class ParticleClass> class LeafClass, - int OctreeHeight, int SubtreeHeight> -class FFmmAlgorithmThreadUs : protected FAssertable{ - // To reduce the size of variable type based on foctree in this file - typedef FOctree<ParticleClass, CellClass, LeafClass, OctreeHeight, SubtreeHeight> Octree; - typedef typename FOctree<ParticleClass, CellClass,LeafClass, OctreeHeight, SubtreeHeight>::Iterator OctreeIterator; - typedef KernelClass<ParticleClass, CellClass, OctreeHeight> Kernel; - - Octree* const tree; //< The octree to work on - Kernel* kernels[FThreadNumbers]; //< The kernels - - FDEBUG(FTic counterTime); //< In case of debug: to count the elapsed time - FDEBUG(FTic computationCounter); //< In case of debug: to count computation time - - OctreeIterator* iterArray; - -public: - /** The constructor need the octree and the kernels used for computation - * @param inTree the octree to work on - * @param inKernels the kernels to call - * An assert is launched if one of the arguments is null - */ - FFmmAlgorithmThreadUs(Octree* const inTree, Kernel* const inKernels) - : tree(inTree) , iterArray(0) { - - assert(tree, "tree cannot be null", __LINE__, __FILE__); - assert(kernels, "kernels cannot be null", __LINE__, __FILE__); - - for(int idxThread = 0 ; idxThread < FThreadNumbers ; ++idxThread){ - this->kernels[idxThread] = new KernelClass<ParticleClass, CellClass, OctreeHeight>(*inKernels); - } - - FDEBUG(FDebug::Controller << "FFmmAlgorithmThreadUs\n"); - } - - /** Default destructor */ - virtual ~FFmmAlgorithmThreadUs(){ - for(int idxThread = 0 ; idxThread < FThreadNumbers ; ++idxThread){ - delete this->kernels[idxThread]; - } - } - - /** - * To execute the fmm algorithm - * Call this function to run the complete algorithm - */ - void execute(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - - // Count leaf - int leafs = 0; - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - do{ - ++leafs; - } while(octreeIterator.moveRight()); - iterArray = new OctreeIterator[leafs]; - assert(iterArray, "iterArray bad alloc", __LINE__, __FILE__); - - for(int idxThread = 0 ; idxThread < FThreadNumbers ; ++idxThread){ - this->kernels[idxThread]->init(); - } - - bottomPass(); - upwardPass(); - - downardPass(); - - directPass(); - - delete [] iterArray; - iterArray = 0; - - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** P2M */ - void bottomPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Bottom Pass\n").write(FDebug::Flush) ); - FDEBUG( counterTime.tic() ); - - OctreeIterator octreeIterator(tree); - int leafs = 0; - // Iterate on leafs - octreeIterator.gotoBottomLeft(); - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - // We need the current cell that represent the leaf - // and the list of particles - myThreadkernels->P2M( iterArray[idxLeafs].getCurrentCell() , iterArray[idxLeafs].getCurrentListSources()); - } - } - FDEBUG(computationCounter.tac()); - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << computationCounter.elapsed() << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** M2M */ - void upwardPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Upward Pass\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - // Start from leal level - 1 - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - octreeIterator.moveUp(); - OctreeIterator avoidGotoLeftIterator(octreeIterator); - - // for each levels - for(int idxLevel = OctreeHeight - 2 ; idxLevel > 1 ; --idxLevel ){ - int leafs = 0; - // for each cells - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - avoidGotoLeftIterator.moveUp(); - octreeIterator = avoidGotoLeftIterator;// equal octreeIterator.moveUp(); octreeIterator.gotoLeft(); - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - // We need the current cell and the child - // child is an array (of 8 child) that may be null - myThreadkernels->M2M( iterArray[idxLeafs].getCurrentCell() , iterArray[idxLeafs].getCurrentChild(), idxLevel); - } - } - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** M2L L2L */ - void downardPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Downward Pass (M2L)\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - { // first M2L - OctreeIterator octreeIterator(tree); - octreeIterator.moveDown(); - OctreeIterator avoidGotoLeftIterator(octreeIterator); - - // for each levels - for(int idxLevel = 2 ; idxLevel < OctreeHeight ; ++idxLevel ){ - int leafs = 0; - // for each cells - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - avoidGotoLeftIterator.moveDown(); - octreeIterator = avoidGotoLeftIterator; - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - CellClass* neighbors[208]; - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - const int counter = tree->getDistantNeighbors(neighbors, iterArray[idxLeafs].getCurrentGlobalIndex(),idxLevel); - if(counter) myThreadkernels->M2L( iterArray[idxLeafs].getCurrentCell() , neighbors, counter, idxLevel); - } - } - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } - } - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - - FDEBUG( FDebug::Controller.write("\tStart Downward Pass (L2L)\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( totalComputation = 0 ); - { // second L2L - OctreeIterator octreeIterator(tree); - octreeIterator.moveDown(); - - OctreeIterator avoidGotoLeftIterator(octreeIterator); - - const int heightMinusOne = OctreeHeight - 1; - // for each levels exepted leaf level - for(int idxLevel = 2 ; idxLevel < heightMinusOne ; ++idxLevel ){ - int leafs = 0; - // for each cells - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - avoidGotoLeftIterator.moveDown(); - octreeIterator = avoidGotoLeftIterator; - - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - myThreadkernels->L2L( iterArray[idxLeafs].getCurrentCell() , iterArray[idxLeafs].getCurrentChild(), idxLevel); - } - } - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** P2P */ - void directPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Direct Pass\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - - int leafs = 0; - { - OctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - // for each leafs - do{ - iterArray[leafs] = octreeIterator; - ++leafs; - } while(octreeIterator.moveRight()); - } - - const int heightMinusOne = OctreeHeight - 1; - FDEBUG(computationCounter.tic()); - #pragma omp parallel num_threads(FThreadNumbers) - { - Kernel * const myThreadkernels = kernels[omp_get_thread_num()]; - // There is a maximum of 26 neighbors - FList<ParticleClass*>* neighbors[26]; - - #pragma omp for - for(int idxLeafs = 0 ; idxLeafs < leafs ; ++idxLeafs){ - myThreadkernels->L2P(iterArray[idxLeafs].getCurrentCell(), iterArray[idxLeafs].getCurrentListTargets()); - // need the current particles and neighbors particles - const int counter = tree->getLeafsNeighbors(neighbors, iterArray[idxLeafs].getCurrentGlobalIndex(),heightMinusOne); - myThreadkernels->P2P( iterArray[idxLeafs].getCurrentListTargets(), iterArray[idxLeafs].getCurrentListSources() , neighbors, counter); - } - } - FDEBUG(computationCounter.tac()); - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << computationCounter.elapsed() << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - -}; - - -#endif //FFMMALGORITHMTHREADUS_HPP - -// [--LICENSE--] diff --git a/Sources/Core/FFmmAlgorithmTsm.hpp b/Sources/Core/FFmmAlgorithmTsm.hpp deleted file mode 100644 index ac1ceacdc..000000000 --- a/Sources/Core/FFmmAlgorithmTsm.hpp +++ /dev/null @@ -1,288 +0,0 @@ -#ifndef FFMMALGORITHMTSM_HPP -#define FFMMALGORITHMTSM_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FAssertable.hpp" -#include "../Utils/FDebug.hpp" -#include "../Utils/FTrace.hpp" -#include "../Utils/FTic.hpp" - -#include "../Containers/FOctree.hpp" - - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmmAlgorithmTsm -* @brief -* Please read the license -* -* This class is a basic FMM algorithm -* It just iterates on a tree and call the kernels with good arguments. -* -* Of course this class does not deallocate pointer given in arguements. -*/ -template<template< class ParticleClass, class CellClass, int OctreeHeight> class KernelClass, -class ParticleClass, class CellClass, -template<class ParticleClass> class LeafClass, -int OctreeHeight, int SubtreeHeight> - class FFmmAlgorithmTsm : protected FAssertable{ - // To reduce the size of variable type based on foctree in this file - typedef FOctree<ParticleClass, CellClass, LeafClass, OctreeHeight, SubtreeHeight> Octree; - typedef typename FOctree<ParticleClass, CellClass,LeafClass, OctreeHeight, SubtreeHeight>::Iterator FOctreeIterator; - - Octree* const tree; //< The octree to work on - KernelClass<ParticleClass, CellClass, OctreeHeight>* const kernels; //< The kernels - - FDEBUG(FTic counterTime); //< In case of debug: to count the elapsed time - FDEBUG(FTic computationCounter); //< In case of debug: to count computation time - -public: - /** The constructor need the octree and the kernels used for computation - * @param inTree the octree to work on - * @param inKernels the kernels to call - * An assert is launched if one of the arguments is null - */ - FFmmAlgorithmTsm(Octree* const inTree, KernelClass<ParticleClass,CellClass,OctreeHeight>* const inKernels) - : tree(inTree) , kernels(inKernels) { - - assert(tree, "tree cannot be null", __LINE__, __FILE__); - assert(kernels, "kernels cannot be null", __LINE__, __FILE__); - - FDEBUG(FDebug::Controller << "FFmmAlgorithmTsm\n"); - } - - /** Default destructor */ - virtual ~FFmmAlgorithmTsm(){ - } - - /** - * To execute the fmm algorithm - * Call this function to run the complete algorithm - */ - void execute(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - - kernels->init(); - - bottomPass(); - upwardPass(); - - downardPass(); - - directPass(); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** P2M */ - void bottomPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Bottom Pass\n").write(FDebug::Flush) ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - FOctreeIterator octreeIterator(tree); - - // Iterate on leafs - octreeIterator.gotoBottomLeft(); - do{ - // We need the current cell that represent the leaf - // and the list of particles - FDEBUG(computationCounter.tic()); - FList<ParticleClass*>* const sources = octreeIterator.getCurrentListSources(); - if(sources->getSize()){ - octreeIterator.getCurrentCell()->setSourcesChildTrue(); - kernels->P2M( octreeIterator.getCurrentCell() , sources); - } - if(octreeIterator.getCurrentListTargets()->getSize()){ - octreeIterator.getCurrentCell()->setTargetsChildTrue(); - } - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } while(octreeIterator.moveRight()); - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** M2M */ - void upwardPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Upward Pass\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - // Start from leal level - 1 - FOctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - octreeIterator.moveUp(); - - FOctreeIterator avoidGotoLeftIterator(octreeIterator); - - // for each levels - for(int idxLevel = OctreeHeight - 2 ; idxLevel > 1 ; --idxLevel ){ - // for each cells - do{ - // We need the current cell and the child - // child is an array (of 8 child) that may be null - FDEBUG(computationCounter.tic()); - - CellClass* potentialChild[8]; - CellClass** const realChild = octreeIterator.getCurrentChild(); - CellClass* const currentCell = octreeIterator.getCurrentCell(); - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - potentialChild[idxChild] = 0; - if(realChild[idxChild]){ - if(realChild[idxChild]->hasSourcesChild()){ - currentCell->setSourcesChildTrue(); - potentialChild[idxChild] = realChild[idxChild]; - } - if(realChild[idxChild]->hasTargetsChild()){ - currentCell->setTargetsChildTrue(); - } - } - } - kernels->M2M( currentCell , potentialChild, idxLevel); - - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } while(octreeIterator.moveRight()); - - avoidGotoLeftIterator.moveUp(); - octreeIterator = avoidGotoLeftIterator;// equal octreeIterator.moveUp(); octreeIterator.gotoLeft(); - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** M2L L2L */ - void downardPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Downward Pass (M2L)\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - { // first M2L - FOctreeIterator octreeIterator(tree); - octreeIterator.moveDown(); - - FOctreeIterator avoidGotoLeftIterator(octreeIterator); - - CellClass* neighbors[208]; - // for each levels - for(int idxLevel = 2 ; idxLevel < OctreeHeight ; ++idxLevel ){ - // for each cells - do{ - FDEBUG(computationCounter.tic()); - CellClass* const currentCell = octreeIterator.getCurrentCell(); - if(currentCell->hasTargetsChild()){ - const int counter = tree->getDistantNeighbors(neighbors, octreeIterator.getCurrentGlobalIndex(),idxLevel); - int offsetTargetNeighbors = 0; - for(int idxRealNeighbors = 0 ; idxRealNeighbors < counter ; ++idxRealNeighbors, ++offsetTargetNeighbors){ - if(neighbors[idxRealNeighbors]->hasSourcesChild()){ - if(idxRealNeighbors != offsetTargetNeighbors){ - neighbors[offsetTargetNeighbors] = neighbors[idxRealNeighbors]; - } - } - else{ - --offsetTargetNeighbors; - } - } - if(offsetTargetNeighbors){ - kernels->M2L( currentCell , neighbors, offsetTargetNeighbors, idxLevel); - } - } - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } while(octreeIterator.moveRight()); - - avoidGotoLeftIterator.moveDown(); - octreeIterator = avoidGotoLeftIterator; - } - } - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - - FDEBUG( FDebug::Controller.write("\tStart Downward Pass (L2L)\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( totalComputation = 0 ); - { // second L2L - FOctreeIterator octreeIterator(tree); - octreeIterator.moveDown(); - - FOctreeIterator avoidGotoLeftIterator(octreeIterator); - - const int heightMinusOne = OctreeHeight - 1; - // for each levels exepted leaf level - for(int idxLevel = 2 ; idxLevel < heightMinusOne ; ++idxLevel ){ - // for each cells - do{ - FDEBUG(computationCounter.tic()); - CellClass* potentialChild[8]; - CellClass** const realChild = octreeIterator.getCurrentChild(); - CellClass* const currentCell = octreeIterator.getCurrentCell(); - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - if(realChild[idxChild] && realChild[idxChild]->hasTargetsChild()){ - potentialChild[idxChild] = realChild[idxChild]; - } - else{ - potentialChild[idxChild] = 0; - } - } - kernels->L2L( currentCell , potentialChild, idxLevel); - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } while(octreeIterator.moveRight()); - - avoidGotoLeftIterator.moveDown(); - octreeIterator = avoidGotoLeftIterator; - } - } - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - - /** P2P */ - void directPass(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - FDEBUG( FDebug::Controller.write("\tStart Direct Pass\n").write(FDebug::Flush); ); - FDEBUG( counterTime.tic() ); - FDEBUG( double totalComputation = 0 ); - - const int heightMinusOne = OctreeHeight - 1; - - FOctreeIterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - // There is a maximum of 26 neighbors - FList<ParticleClass*>* neighbors[26]; - // for each leafs - do{ - FDEBUG(computationCounter.tic()); - kernels->L2P(octreeIterator.getCurrentCell(), octreeIterator.getCurrentListTargets()); - // need the current particles and neighbors particles - const int counter = tree->getLeafsNeighbors(neighbors, octreeIterator.getCurrentGlobalIndex(),heightMinusOne); - kernels->P2P( octreeIterator.getCurrentListTargets(), octreeIterator.getCurrentListSources() , neighbors, counter); - FDEBUG(computationCounter.tac()); - FDEBUG(totalComputation += computationCounter.elapsed()); - } while(octreeIterator.moveRight()); - - FDEBUG( counterTime.tac() ); - FDEBUG( FDebug::Controller << "\tFinished (" << counterTime.elapsed() << "s)\n" ); - FDEBUG( FDebug::Controller << "\t\t Computation : " << totalComputation << " s\n" ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - } - -}; - - -#endif //FFMMALGORITHMTSM_HPP - -// [--LICENSE--] diff --git a/Sources/Extenssions/FExtendCellType.hpp b/Sources/Extenssions/FExtendCellType.hpp deleted file mode 100644 index 6b751156b..000000000 --- a/Sources/Extenssions/FExtendCellType.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef FEXTENDCELLTYPE_HPP -#define FEXTENDCELLTYPE_HPP -// /!\ Please, you must read the license at the bottom of this page - - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FExtendCellType -* Please read the license -* This class is an extenssion. -* It proposes a target/source extenssion for cell. -* Because cells may have child that contains only -* sources or targets (in Tsm system) then it is important -* to not compute for nothing. -*/ -class FExtendCellType { -protected: - /** Particle potential type */ - static const int Neither = 0; - static const int ContainsSources = 1; - static const int ContainsTargets = 2; - - /** Current type */ - int type; - -public: - /** Default constructor */ - FExtendCellType() : type(Neither) { - } - - /** Copy constructor */ - FExtendCellType(const FExtendCellType& other) : type(other.type) { - } - - /** Destructor */ - virtual ~FExtendCellType(){ - } - - /** Copy operator */ - FExtendCellType& operator=(const FExtendCellType& other) { - this->type = other.type; - return *this; - } - - /** To know if a cell has sources */ - bool hasSourcesChild() const { - return this->type & ContainsSources; - } - - /** To know if a cell has targets */ - bool hasTargetsChild() const { - return this->type & ContainsTargets; - } - - /** To set cell as sources container */ - void setSourcesChildTrue() { - this->type |= ContainsSources; - } - - /** To set cell as targets container */ - void setTargetsChildTrue() { - this->type |= ContainsTargets; - } -}; - - -#endif //FEXTENDCELLTYPE_HPP - -// [--LICENSE--] diff --git a/Sources/Extenssions/FExtendForces.hpp b/Sources/Extenssions/FExtendForces.hpp deleted file mode 100644 index cc4f4070f..000000000 --- a/Sources/Extenssions/FExtendForces.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef FEXTENDFORCES_HPP -#define FEXTENDFORCES_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FGlobal.hpp" -#include "../Utils/F3DPosition.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FExtendForces -* Please read the license -* -* This class is an extenssion. -* It proposes a 3d array as a forces vector. -*/ -class FExtendForces { -protected: - F3DPosition forces; //< 3D vector stored in a position object - -public: - /** Default constructor */ - FExtendForces() { - } - - /** Copy constructor */ - FExtendForces(const FExtendForces& other) : forces(other.forces) { - } - - /** Destructor */ - virtual ~FExtendForces(){ - } - - /** Copy operator */ - FExtendForces& operator=(const FExtendForces& other) { - this->forces = other.forces; - return *this; - } - - /** Return the forces */ - F3DPosition getForces() const { - return this->forces; - } - - /** Set Forces */ - void setForces(const F3DPosition& inForces) { - this->forces = inForces; - } - - /** Set Forces with 3 FReals */ - void setForces(const FReal inFx, const FReal inFy, const FReal inFz) { - this->forces.setX(inFx); - this->forces.setY(inFy); - this->forces.setZ(inFz); - } - -}; - - -#endif //FEXTENDFORCES_HPP - -// [--LICENSE--] diff --git a/Sources/Extenssions/FExtendMortonIndex.hpp b/Sources/Extenssions/FExtendMortonIndex.hpp deleted file mode 100644 index 7e7d5c052..000000000 --- a/Sources/Extenssions/FExtendMortonIndex.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef FEXTENDMORTONINDEX_HPP -#define FEXTENDMORTONINDEX_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Containers/FTreeCoordinate.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FExtendMortonIndex -* Please read the license -* This class is an extenssion. -* It proposes a mortonIndex. -*/ -class FExtendMortonIndex { -protected: - MortonIndex mortonIndex; //< Morton index (need by most elements) - -public: - /** Default constructor */ - FExtendMortonIndex() : mortonIndex(0) { - } - - /** Copy constructor */ - FExtendMortonIndex(const FExtendMortonIndex& other) : mortonIndex(other.mortonIndex) { - } - - /** Destructor */ - virtual ~FExtendMortonIndex(){ - } - - /** Copy operator */ - FExtendMortonIndex& operator=(const FExtendMortonIndex& other) { - this->mortonIndex = other.mortonIndex; - return *this; - } - - /** To get the morton index */ - MortonIndex getMortonIndex() const { - return this->mortonIndex; - } - - /** To set the morton index */ - void setMortonIndex(const MortonIndex inMortonIndex) { - this->mortonIndex = inMortonIndex; - } - -}; - - -#endif //FEXTENDMORTONINDEX_HPP - -// [--LICENSE--] diff --git a/Sources/Extenssions/FExtendParticleType.hpp b/Sources/Extenssions/FExtendParticleType.hpp deleted file mode 100644 index 13f550374..000000000 --- a/Sources/Extenssions/FExtendParticleType.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef FEXTENDPARTICLETYPE_HPP -#define FEXTENDPARTICLETYPE_HPP -// /!\ Please, you must read the license at the bottom of this page - - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FExtendParticleType -* Please read the license -* This class is an extenssion. -* It proposes a target/source extenssion. -*/ -class FExtendParticleType { -protected: - /** Particle potential type */ - enum Type { - Source, - Target, - Undef - }; - - /** Current type */ - Type type; - -public: - /** Default constructor */ - FExtendParticleType() : type(Undef) { - } - - /** Copy constructor */ - FExtendParticleType(const FExtendParticleType& other) : type(other.type) { - } - - /** Destructor */ - virtual ~FExtendParticleType(){ - } - - /** Copy operator */ - FExtendParticleType& operator=(const FExtendParticleType& other) { - this->type = other.type; - return *this; - } - - /** To get the type */ - Type getParticleType() const { - return this->type; - } - - /** To set the type */ - void setParticleType(const Type inType) { - this->type = inType; - } - - /** To know if a particle is a target */ - bool isTarget() const{ - return this->type == Target; - } - - /** To know if a particle is a source */ - bool isSource() const{ - return this->type == Source; - } - - /** To know if a particle has an undefined type */ - bool isUndefinedType() const{ - return this->type == Undef; - } - - /** To know if a particle is a target */ - void setAsTarget() { - this->type = Target; - } - - /** To know if a particle is a source */ - void setAsSource() { - this->type = Source; - } - -}; - - -#endif //FEXTENDPARTICLETYPE_HPP - -// [--LICENSE--] diff --git a/Sources/Extenssions/FExtendPhysicalValue.hpp b/Sources/Extenssions/FExtendPhysicalValue.hpp deleted file mode 100644 index afed36349..000000000 --- a/Sources/Extenssions/FExtendPhysicalValue.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef FExtendPhysicalValue_HPP -#define FExtendPhysicalValue_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FGlobal.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FExtendPhysicalValue -* Please read the license -* This class is an extenssion. -* It proposes a physicalValue (FReal). -*/ -class FExtendPhysicalValue { -protected: - FReal physicalValue; //< A simple physicalValue - -public: - /** Default constructor */ - FExtendPhysicalValue() : physicalValue(0) { - } - - /** Copy constructor */ - FExtendPhysicalValue(const FExtendPhysicalValue& other) : physicalValue(other.physicalValue) { - } - - /** Destructor */ - virtual ~FExtendPhysicalValue(){ - } - - /** Copy Constructor */ - FExtendPhysicalValue& operator=(const FExtendPhysicalValue& other) { - this->physicalValue = other.physicalValue; - return *this; - } - - /** To get the physicalValue */ - FReal getPhysicalValue() const { - return this->physicalValue; - } - - /** To set the physicalValue */ - void setPhysicalValue(const FReal inphysicalValue) { - this->physicalValue = inphysicalValue; - } - -}; - - -#endif //FExtendPhysicalValue_HPP - -// [--LICENSE--] diff --git a/Sources/Extenssions/FExtendPosition.hpp b/Sources/Extenssions/FExtendPosition.hpp deleted file mode 100644 index 959b152d4..000000000 --- a/Sources/Extenssions/FExtendPosition.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef FEXTENDPOSITION_HPP -#define FEXTENDPOSITION_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FGlobal.hpp" -#include "../Utils/F3DPosition.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FExtendPosition -* Please read the license -* This class is an extenssion. -* It proposes a mortonIndex. -*/ -class FExtendPosition { -protected: - F3DPosition position; //< The position - -public: - /** Default constructor */ - FExtendPosition() { - } - - /** Copy constructor */ - FExtendPosition(const FExtendPosition& other) : position(other.position) { - } - - /** Destructor */ - virtual ~FExtendPosition(){ - } - - /** Copy operator */ - FExtendPosition& operator=(const FExtendPosition& other) { - this->position = other.position; - return *this; - } - - /** To get the position */ - F3DPosition getPosition() const { - return this->position; - } - - /** To set the position */ - void setPosition(const F3DPosition& inPosition) { - this->position = inPosition; - } - - /** To set the position from 3 FReals */ - void setPosition(const FReal inX, const FReal inY, const FReal inZ) { - this->position.setX(inX); - this->position.setY(inY); - this->position.setZ(inZ); - } - -}; - - -#endif //FEXTENDPOSITION_HPP - -// [--LICENSE--] diff --git a/Sources/Extenssions/FExtendPotential.hpp b/Sources/Extenssions/FExtendPotential.hpp deleted file mode 100644 index 09629d608..000000000 --- a/Sources/Extenssions/FExtendPotential.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef FEXTENDPOTENTIAL_HPP -#define FEXTENDPOTENTIAL_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FGlobal.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FExtendPotential -* Please read the license -* This class is an extenssion. -* It proposes a Potential (FReal). -*/ -class FExtendPotential { -protected: - FReal potential; //< The potential extended - -public: - /** Default constructor */ - FExtendPotential() : potential(0) { - } - - /** Copy constructor */ - FExtendPotential(const FExtendPotential& other) : potential(other.potential) { - } - - /** Destructor */ - virtual ~FExtendPotential(){ - } - - /** Copy operator */ - FExtendPotential& operator=(const FExtendPotential& other) { - this->potential = other.potential; - return *this; - } - - /** To get the potential */ - FReal getPotential() const { - return this->potential; - } - - /** To set the potential */ - void setPotential(const FReal inPotential) { - this->potential = inPotential; - } - -}; - - -#endif //FEXTENDPOTENTIAL_HPP - -// [--LICENSE--] diff --git a/Sources/Files/FAbstractLoader.hpp b/Sources/Files/FAbstractLoader.hpp deleted file mode 100644 index e7d3a4421..000000000 --- a/Sources/Files/FAbstractLoader.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef FABSTRACTLOADER_HPP -#define FABSTRACTLOADER_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FGlobal.hpp" -class F3DPosition; - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FAbstractLoader -* Please read the license -* -* This class defined the FMB usual loader. A loader is the component -* that fills an octree. -* -* If you want to use a specific file format you then need to inherite from this loader -* and implemente several methods. -* -* Please look at FBasicLoader or FFmaLoader to see an example. -* -* @warning Inherite from this class when defining a loader class -*/ -template <class ParticleClass> -class FAbstractLoader { -public: - /** Default destructor */ - virtual ~FAbstractLoader(){ - } - - /** - * Get the number of particles for this simulation - * @return number of particles that the loader can fill - */ - virtual long getNumberOfParticles() const = 0; - - /** - * Get the center of the simulation box - * @return box center needed by the octree - */ - virtual F3DPosition getCenterOfBox() const = 0; - - /** - * Get the simulation box width - * @return box width needed by the octree - */ - virtual FReal getBoxWidth() const = 0; - - /** - * To know if the loader is valide (file opened, etc.) - * @return true if file is open - */ - virtual bool isValide() const = 0; - - /** - * Fill the next particle - * @param inParticle the particle to fill - */ - virtual void fillParticle(ParticleClass* const inParticle) = 0; -}; - - -#endif //FABSTRACTLOADER_HPP - -// [--LICENSE--] diff --git a/Sources/Files/FBasicLoader.hpp b/Sources/Files/FBasicLoader.hpp deleted file mode 100644 index 95baf8988..000000000 --- a/Sources/Files/FBasicLoader.hpp +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef FBASICLOADER_HPP -#define FBASICLOADER_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include <iostream> -#include <fstream> - -#include "../Utils/FGlobal.hpp" -#include "FAbstractLoader.hpp" -#include "../Utils/F3DPosition.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FBasicLoader -* Please read the license -* -* Load a file with a format like : -* NB_particles Box_width Box_X Box_Y Box_Z // init -* X Y Z // one particle by line -* .... -* <code> -* FBasicLoader<FBasicParticle> loader("../FMB++/Tests/particles.basic.txt"); <br> -* if(!loader.isValide()){ <br> -* std::cout << "Loader Error\n"; <br> -* return 1; <br> -* } <br> -* <br> -* FOctree<FBasicParticle, TestCell, FSimpleLeaf, 10, 3> tree(loader.getBoxWidth(),loader.getCenterOfBox()); <br> -* <br> -* for(int idx = 0 ; idx < loader.getNumberOfParticles() ; ++idx){ <br> -* FBasicParticle* const part = new FBasicParticle(); <br> -* loader.fillParticle(part); <br> -* tree.insert(part); <br> -* } <br> -* </code> -*/ -template <class ParticleClass> -class FBasicLoader : public FAbstractLoader<ParticleClass> { -protected: - std::ifstream file; //< The file to read - F3DPosition centerOfBox; //< The center of box read from file - FReal boxWidth; //< the box width read from file - int nbParticles; //< the number of particles read from file - -public: - /** - * The constructor need the file name - * @param filename the name of the file to open - * you can test if file is successfuly open by calling isValide() - */ - FBasicLoader(const char* const filename): file(filename,std::ifstream::in){ - // test if open - if(this->file.is_open()){ - FReal x,y,z; - this->file >> this->nbParticles >> this->boxWidth >> x >> y >> z; - this->centerOfBox.setPosition(x,y,z); - } - else { - this->boxWidth = 0; - this->nbParticles = 0; - } - } - - /** - * Default destructor, simply close the file - */ - virtual ~FBasicLoader(){ - file.close(); - } - - /** - * To know if file is open and ready to read - * @return true if loader can work - */ - bool isValide() const{ - return this->file.is_open() && !this->file.eof(); - } - - /** - * To get the number of particles from this loader - * @param the number of particles the loader can fill - */ - long getNumberOfParticles() const{ - return this->nbParticles; - } - - /** - * The center of the box from the simulation file opened by the loader - * @return box center - */ - F3DPosition getCenterOfBox() const{ - return this->centerOfBox; - } - - /** - * The box width from the simulation file opened by the loader - * @return box width - */ - FReal getBoxWidth() const{ - return this->boxWidth; - } - - /** - * Fill a particle - * @warning to work with the loader, particles has to expose a setPosition method - * @param the particle to fill - */ - void fillParticle(ParticleClass* const inParticle){ - FReal x,y,z; - this->file >> x >> y >> z; - inParticle->setPosition(F3DPosition(x,y,z)); - } - -}; - - -#endif //FBASICLOADER_HPP - -// [--LICENSE--] diff --git a/Sources/Files/FFmaLoader.hpp b/Sources/Files/FFmaLoader.hpp deleted file mode 100644 index 7a2b4fd51..000000000 --- a/Sources/Files/FFmaLoader.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef FFMALOADER_HPP -#define FFMALOADER_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include <iostream> -#include <fstream> - -#include "../Utils/FGlobal.hpp" -#include "FAbstractLoader.hpp" -#include "../Utils/F3DPosition.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmaLoader -* Please read the license -* -* Load a file with a format like : -* NB_particles Box_width Box_X Box_Y Box_Z // init -* X Y Z // one particle by line -* .... -* <code> -* FFmaLoader<FBasicParticle> loader("../FMB++/Tests/particles.basic.txt"); <br> -* if(!loader.isValide()){ <br> -* std::cout << "Loader Error\n"; <br> -* return 1; <br> -* } <br> -* <br> -* FOctree<FBasicParticle, TestCell, FSimpleLeaf, 10, 3> tree(loader.getBoxWidth(),loader.getCenterOfBox()); <br> -* <br> -* for(int idx = 0 ; idx < loader.getNumberOfParticles() ; ++idx){ <br> -* FBasicParticle* const part = new FBasicParticle(); <br> -* loader.fillParticle(part); <br> -* tree.insert(part); <br> -* } <br> -* </code> -* -* Particle has to extend {FExtendPhysicalValue,FExtendPosition} -*/ -template <class ParticleClass> -class FFmaLoader : public FAbstractLoader<ParticleClass> { -protected: - std::ifstream file; //< The file to read - F3DPosition centerOfBox; //< The center of box read from file - FReal boxWidth; //< the box width read from file - int nbParticles; //< the number of particles read from file - -public: - /** - * The constructor need the file name - * @param filename the name of the file to open - * you can test if file is successfuly open by calling isValide() - */ - FFmaLoader(const char* const filename): file(filename,std::ifstream::in){ - // test if open - if(this->file.is_open()){ - FReal x,y,z; - this->file >> this->nbParticles >> this->boxWidth >> x >> y >> z; - this->centerOfBox.setPosition(x,y,z); - this->boxWidth *= 2; - } - else { - this->boxWidth = 0; - this->nbParticles = 0; - } - } - - /** - * Default destructor, simply close the file - */ - virtual ~FFmaLoader(){ - file.close(); - } - - /** - * To know if file is open and ready to read - * @return true if loader can work - */ - bool isValide() const{ - return this->file.is_open() && !this->file.eof(); - } - - /** - * To get the number of particles from this loader - * @param the number of particles the loader can fill - */ - long getNumberOfParticles() const{ - return this->nbParticles; - } - - /** - * The center of the box from the simulation file opened by the loader - * @return box center - */ - F3DPosition getCenterOfBox() const{ - return this->centerOfBox; - } - - /** - * The box width from the simulation file opened by the loader - * @return box width - */ - FReal getBoxWidth() const{ - return this->boxWidth; - } - - /** - * Fill a particle - * @warning to work with the loader, particles has to expose a setPosition method - * @param the particle to fill - */ - void fillParticle(ParticleClass* const inParticle){ - FReal x,y,z,data; - this->file >> x >> y >> z >> data; - inParticle->setPosition(x,y,z); - inParticle->setPhysicalValue(data); - } - -}; - - -#endif //FFmaLoader_HPP - -// [--LICENSE--] diff --git a/Sources/Files/FFmaScanfLoader.hpp b/Sources/Files/FFmaScanfLoader.hpp deleted file mode 100644 index 065256bad..000000000 --- a/Sources/Files/FFmaScanfLoader.hpp +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef FFMASCANFLOADER_HPP -#define FFMASCANFLOADER_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include <iostream> -#include <fstream> - -#include "../Utils/FGlobal.hpp" -#include "FAbstractLoader.hpp" -#include "../Utils/F3DPosition.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmaScanfLoader -* Please read the license -* -* Load a file with a format like : -* NB_particles Box_width Box_X Box_Y Box_Z // init -* X Y Z // one particle by line -* .... -* <code> -* FFmaScanfLoader<FBasicParticle> loader("../FMB++/Tests/particles.basic.txt"); <br> -* if(!loader.isValide()){ <br> -* std::cout << "Loader Error\n"; <br> -* return 1; <br> -* } <br> -* <br> -* FOctree<FBasicParticle, TestCell, FSimpleLeaf, 10, 3> tree(loader.getBoxWidth(),loader.getCenterOfBox()); <br> -* <br> -* for(int idx = 0 ; idx < loader.getNumberOfParticles() ; ++idx){ <br> -* FBasicParticle* const part = new FBasicParticle(); <br> -* loader.fillParticle(part); <br> -* tree.insert(part); <br> -* } <br> -* </code> -* -* Particle has to extend {FExtendPhysicalValue,FExtendPosition} -*/ -template <class ParticleClass> -class FFmaScanfLoader : public FAbstractLoader<ParticleClass> { -protected: - FILE* file; //< The file to read - F3DPosition centerOfBox; //< The center of box read from file - FReal boxWidth; //< the box width read from file - int nbParticles; //< the number of particles read from file - -public: - /** - * The constructor need the file name - * @param filename the name of the file to open - * you can test if file is successfuly open by calling isValide() - */ - FFmaScanfLoader(const char* const filename): file(0){ - file = fopen(filename,"r"); - // test if open - if(this->file){ - float x,y,z, fBoxWidth; - const int nbReadElements = fscanf(file,"%d %f %f %f %f",&this->nbParticles,&fBoxWidth,&x,&y,&z); - if(nbReadElements == 5){ - this->boxWidth = fBoxWidth; - this->centerOfBox.setPosition(x,y,z); - this->boxWidth *= 2; - } - else{ - fclose(file); - file = NULL; - } - } - else { - this->boxWidth = 0; - this->nbParticles = 0; - } - } - - /** - * Default destructor, simply close the file - */ - virtual ~FFmaScanfLoader(){ - fclose(file); - } - - /** - * To know if file is open and ready to read - * @return true if loader can work - */ - bool isValide() const{ - return this->file != NULL; - } - - /** - * To get the number of particles from this loader - * @param the number of particles the loader can fill - */ - long getNumberOfParticles() const{ - return this->nbParticles; - } - - /** - * The center of the box from the simulation file opened by the loader - * @return box center - */ - F3DPosition getCenterOfBox() const{ - return this->centerOfBox; - } - - /** - * The box width from the simulation file opened by the loader - * @return box width - */ - FReal getBoxWidth() const{ - return this->boxWidth; - } - - /** - * Fill a particle - * @warning to work with the loader, particles has to expose a setPosition method - * @param the particle to fill - */ - void fillParticle(ParticleClass* const inParticle){ - float x,y,z,data; - const int nbReadElements = fscanf(file,"%f %f %f %f",&x,&y,&z,&data); - if(nbReadElements == 4){ - inParticle->setPosition(x,y,z); - inParticle->setPhysicalValue(data); - } - else{ - fclose(file); - file = NULL; - } - } - -}; - - -#endif //FFMASCANFLOADER_HPP - -// [--LICENSE--] diff --git a/Sources/Files/FFmaTsmLoader.hpp b/Sources/Files/FFmaTsmLoader.hpp deleted file mode 100644 index adcb0b405..000000000 --- a/Sources/Files/FFmaTsmLoader.hpp +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef FFMATSMLOADER_HPP -#define FFMATSMLOADER_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include <iostream> -#include <fstream> - -#include "../Utils/FGlobal.hpp" -#include "FAbstractLoader.hpp" -#include "../Utils/F3DPosition.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmaTsmLoader -* Please read the license -* -* Load a file with a format like : -* NB_particles Box_width Box_X Box_Y Box_Z // init -* X Y Z // one particle by line -* .... -* <code> -* FFmaTsmLoader<FBasicParticle> loader("../FMB++/Tests/particles.basic.txt"); <br> -* if(!loader.isValide()){ <br> -* std::cout << "Loader Error\n"; <br> -* return 1; <br> -* } <br> -* <br> -* FOctree<FBasicParticle, TestCell, FSimpleLeaf, 10, 3> tree(loader.getBoxWidth(),loader.getCenterOfBox()); <br> -* <br> -* for(int idx = 0 ; idx < loader.getNumberOfParticles() ; ++idx){ <br> -* FBasicParticle* const part = new FBasicParticle(); <br> -* loader.fillParticle(part); <br> -* tree.insert(part); <br> -* } <br> -* </code> -* -* Particle has to extend {FExtendPhysicalValue,FExtendPosition} -*/ -template <class ParticleClass> -class FFmaTsmLoader : public FAbstractLoader<ParticleClass> { -protected: - std::ifstream file; //< The file to read - F3DPosition centerOfBox; //< The center of box read from file - FReal boxWidth; //< the box width read from file - int nbParticles; //< the number of particles read from file - -public: - /** - * The constructor need the file name - * @param filename the name of the file to open - * you can test if file is successfuly open by calling isValide() - */ - FFmaTsmLoader(const char* const filename): file(filename,std::ifstream::in){ - // test if open - if(this->file.is_open()){ - FReal x,y,z; - this->file >> this->nbParticles >> this->boxWidth >> x >> y >> z; - this->centerOfBox.setPosition(x,y,z); - this->boxWidth *= 2; - } - else { - this->boxWidth = 0; - this->nbParticles = 0; - } - } - - /** - * Default destructor, simply close the file - */ - virtual ~FFmaTsmLoader(){ - file.close(); - } - - /** - * To know if file is open and ready to read - * @return true if loader can work - */ - bool isValide() const{ - return this->file.is_open() && !this->file.eof(); - } - - /** - * To get the number of particles from this loader - * @param the number of particles the loader can fill - */ - long getNumberOfParticles() const{ - return this->nbParticles; - } - - /** - * The center of the box from the simulation file opened by the loader - * @return box center - */ - F3DPosition getCenterOfBox() const{ - return this->centerOfBox; - } - - /** - * The box width from the simulation file opened by the loader - * @return box width - */ - FReal getBoxWidth() const{ - return this->boxWidth; - } - - /** - * Fill a particle - * @warning to work with the loader, particles has to expose a setPosition method - * @param the particle to fill - */ - void fillParticle(ParticleClass* const inParticle){ - FReal x,y,z,data; - int isTarget; - this->file >> x >> y >> z >> data >> isTarget; - inParticle->setPosition(x,y,z); - inParticle->setPhysicalValue(data); - if(isTarget) inParticle->setAsTarget(); - else inParticle->setAsSource(); - } - -}; - - -#endif //FFMATSMLOADER_HPP - -// [--LICENSE--] diff --git a/Sources/Fmb/FExtendFmbCell.hpp b/Sources/Fmb/FExtendFmbCell.hpp deleted file mode 100644 index 4cf6525d8..000000000 --- a/Sources/Fmb/FExtendFmbCell.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef FEXTENDFMBCELL_HPP -#define FEXTENDFMBCELL_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include <string.h> - -#include "../Utils/FComplexe.hpp" - -#include "FFmbKernels.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FExtendFmbCell -* Please read the license. -* -* This class is an extenssion. -* It is needed by the Fmb Kernels. -*/ -class FExtendFmbCell { -public: - // FMB_Info_P is declared in FAbstractFmbKernels - static const int MultipoleSize = int(((FMB_Info_P)+1) * ((FMB_Info_P)+2) * 0.5); //< The size of the multipole - -protected: - FComplexe multipole_exp[MultipoleSize]; //< For multipole extenssion - FComplexe local_exp[MultipoleSize]; //< For local extenssion - -public: - /** Default constructor */ - FExtendFmbCell() { - } - - /** Constructor */ - FExtendFmbCell(const FExtendFmbCell& other){ - (*this) = other; - } - - /** Default destructor */ - virtual ~FExtendFmbCell(){ - } - - /** Copy constructor */ - FExtendFmbCell& operator=(const FExtendFmbCell& other) { - memcpy(multipole_exp, other.multipole_exp, sizeof(multipole_exp)); - memcpy(local_exp, other.local_exp, sizeof(local_exp)); - return *this; - } - - /** Get Multipole */ - const FComplexe* getMultipole() const { - return this->multipole_exp; - } - /** Get Local */ - const FComplexe* getLocal() const { - return this->local_exp; - } - - /** Get Multipole */ - FComplexe* getMultipole() { - return this->multipole_exp; - } - /** Get Local */ - FComplexe* getLocal() { - return this->local_exp; - } - -}; - - -#endif //FEXTENDFMBCELL_HPP - -// [--LICENSE--] diff --git a/Sources/Fmb/FFmbKernels.hpp b/Sources/Fmb/FFmbKernels.hpp deleted file mode 100644 index 9d738ef21..000000000 --- a/Sources/Fmb/FFmbKernels.hpp +++ /dev/null @@ -1,1488 +0,0 @@ -#ifndef FFMBKERNELS_HPP -#define FFMBKERNELS_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FGlobal.hpp" -#include "../Components/FAbstractKernels.hpp" - -#include "../Containers/FTreeCoordinate.hpp" -#include "../Containers/FList.hpp" - -#include "../Utils/F3DPosition.hpp" -#include "../Utils/FComplexe.hpp" -#include "../Utils/FMath.hpp" -#include "../Utils/FTrace.hpp" - -#include <iostream> - - -// P is a input parameter -static const int FMB_Info_P = 2; - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmbKernels -* @brief -* Please read the license -* -* This code is coming from the fmb library (see documentation to know more about it). -* It is a copy'n paste file with a few modifications. -* To be able to make link between this file and the originals ones you can -* look to the commentary before function or attributes declarations. -* -* This class is abstract because the fmb's algorithm is able to compute -* forces / potential / both -* So this class is the trunk and defines code used for each 3 computations. -* -* Needs cell to extend {FExtendFmbCell} -*/ -template< class ParticleClass, class CellClass, int TreeHeight> -class FFmbKernels : public FAbstractKernels<ParticleClass,CellClass, TreeHeight> { -protected: - - // _GRAVITATIONAL_ - static const int FMB_Info_eps_soft_square = 1; - - // Can be false or not in not blas kernels - static const int FMB_Info_up_to_P_in_M2L = true; - - // Can be FMB_Info_P if user ask to -- if FMB_Info.up_to_P_in_M2L it true - static const int FMB_Info_M2L_P = FMB_Info_up_to_P_in_M2L? FMB_Info_P : 2 * FMB_Info_P; - static const int FMB_Info_M2L_exp_size = ((FMB_Info_M2L_P)+1) * ((FMB_Info_M2L_P)+2) * 0.5; - - // Default value set in main - static const int FMB_Info_ws = 1; - - // INTERACTION_LIST_SIZE_ALONG_1_DIM - static const int size1Dim = (2*(2*(FMB_Info_ws)+1) +1); - // HALF_INTERACTION_LIST_SIZE_ALONG_1_DIM - static const int halphSize1Dim = (2*(FMB_Info_ws)+1); - - // EXPANSION_SIZE(FMB_Info.P) - static const int FMB_Info_exp_size = ((FMB_Info_P)+1) * ((FMB_Info_P)+2) * 0.5; - // NEXP_SIZE(FMB_Info.P) - static const int FMB_Info_nexp_size = (FMB_Info_P + 1) * (FMB_Info_P + 1); - - // Width of the box at the root level - FReal treeWidthAtRoot; - - // transfer_M2M_container - FComplexe transitionM2M[TreeHeight][8][FMB_Info_nexp_size]; - // transfer_L2L_container - FComplexe transitionL2L[TreeHeight][8][FMB_Info_nexp_size]; - - // transfer_container - FComplexe* transferM2L[TreeHeight][size1Dim][size1Dim][size1Dim]; - - //[OK] spherical_harmonic_Outer_coefficients_array - FReal sphereHarmoOuterCoef[FMB_Info_M2L_P+1]; - //[OK] spherical_harmonic_Inner_coefficients_array - FReal sphereHarmoInnerCoef[FMB_Info_M2L_exp_size]; - - FComplexe current_thread_Y[FMB_Info_exp_size]; - - // p_Y_theta_derivated - FComplexe current_thread_Y_theta_derivated[FMB_Info_exp_size]; - - - // pow_of_I_array - static const FReal PiArrayInner[4]; - // pow_of_O_array - static const FReal PiArrayOuter[4]; - - // To store spherical position - struct Spherical { - FReal r, cosTheta, sinTheta, phi; - }; - - int expansion_Redirection_array_for_j[FMB_Info_M2L_P + 1 ]; - - // To know if we use mutal version - const bool UseMutual; - - ////////////////////////////////////////////////////////////////// - // Allocation - ////////////////////////////////////////////////////////////////// - - void expansion_Redirection_array_for_j_Initialize() { - for( int h = 0; h <= FMB_Info_M2L_P ; ++h ){ - expansion_Redirection_array_for_j[h] = static_cast<int>( h * ( h + 1 ) * 0.5 ); - } - } - - //spherical_harmonic_Outer_and_Inner_coefficients_array_Initialize - void sphericalHarmonicInitialize(){ - // Outer coefficients: - //std::cout << "sphereHarmoOuterCoef\n"; - FReal factOuter = 1.0; - // in FMB code stoped at <= FMB_Info_M2L_P but this is not sufficient - for(int idxP = 0 ; idxP <= FMB_Info_M2L_P; factOuter *= (++idxP) ){ - this->sphereHarmoOuterCoef[idxP] = factOuter; - //printf("spherical_harmonic_Outer_coefficients_array %e\n",this->sphereHarmoOuterCoef[idxP]); - //printf("fact_l %e\n",factOuter); - //printf("l %d\n",idxP); - } - - // Inner coefficients: - FReal* currentInner = this->sphereHarmoInnerCoef; - FReal factInner = 1.0; - FReal powN1idxP = 1.0; - //std::cout << "sphereHarmoInnerCoef\n"; - for(int idxP = 0 ; idxP <= this->FMB_Info_M2L_P ; factInner *= (++idxP), powN1idxP = -powN1idxP){ - for(int idxMP = 0, fact_l_m = factInner; idxMP <= idxP ; fact_l_m *= idxP+(++idxMP), ++currentInner){ - *currentInner = powN1idxP / fact_l_m; - //std::cout << (*currentInner) << "\n"; - } - } - - //for(int temp = 0 ; temp < 6 ; ++temp){ - // std::cout << this->sphereHarmoInnerCoef[temp] << "\n"; - //} - } - - - // transfer_L2L_Allocate - // transfer_M2M_Allocate - // transfer_M2L_Allocate - void transferAllocate(){ - // M2M L2L - /*this->transitionM2M = new FComplexe**[TreeHeight]; - this->transitionL2L = new FComplexe**[TreeHeight]; - - for(int idxLevel = 0 ; idxLevel < TreeHeight ; ++idxLevel){ - - this->transitionM2M[idxLevel] = new FComplexe*[8]; - this->transitionL2L[idxLevel] = new FComplexe*[8]; - - for(long idxChild = 0; idxChild < 8; ++idxChild){ - this->transitionM2M[idxLevel][idxChild] = new FComplexe[FMB_Info_exp_size]; - this->transitionL2L[idxLevel][idxChild] = new FComplexe[FMB_Info_exp_size]; - } - }*/ - // M2L - //this->transferM2L = new FComplexe****[TreeHeight+1]; - - for(int idxLevel = 0; idxLevel < TreeHeight; ++idxLevel){ - //this->transferM2L[idxLevel] = new FComplexe***[this->size1Dim]; - - for(long idxD1 = 0 ; idxD1 < this->size1Dim; ++idxD1){ - //this->transferM2L[idxLevel][idxD1] = new FComplexe**[this->size1Dim]; - - for(long idxD2 = 0; idxD2 < this->size1Dim; ++idxD2){ - //this->transferM2L[idxLevel][idxD1][idxD2] = new FComplexe*[this->size1Dim]; - - for(long idxD3 = 0; idxD3 < this->size1Dim; ++idxD3){ - const int x = idxD1 - this->halphSize1Dim; - const int y = idxD2 - this->halphSize1Dim; - const int z = idxD3 - this->halphSize1Dim; - - if( ( x*x + y*y + z*z ) >= ( 3*this->FMB_Info_ws*this->FMB_Info_ws + 0.1 ) ){ - //[Blas] this->transferM2L[idxLevel][idxD1][idxD2][idxD3] = new FComplexe[this->FMB_Info_exp_size * this->FMB_Info_nexp_size]; - this->transferM2L[idxLevel][idxD1][idxD2][idxD3] = new FComplexe[this->FMB_Info_M2L_exp_size]; - } - else { - this->transferM2L[idxLevel][idxD1][idxD2][idxD3] = NULL; - } - } - } - } - } - } - // transfer_L2L_free - // transfer_M2M_free - // transfer_M2L_free - void transferDeallocate(){ - // M2M L2L - /*for(long idxLevel = 0 ; idxLevel < TreeHeight ; ++idxLevel){ - for(long idxChild = 0; idxChild < 8; ++idxChild){ - delete [] this->transitionM2M[idxLevel][idxChild]; - delete [] this->transitionL2L[idxLevel][idxChild]; - } - delete [] this->transitionM2M[idxLevel]; - delete [] transitionL2L[idxLevel]; - } - delete [] this->transitionM2M; - delete [] this->transitionL2L;*/ - // M2L - for(int idxLevel = 0 ; idxLevel < TreeHeight; ++idxLevel){ - for(long idxD1 = 0 ; idxD1 < this->size1Dim ; ++idxD1){ - for(long idxD2 = 0 ; idxD2 < this->size1Dim ; ++idxD2){ - for(long idxD3 = 0 ; idxD3 < this->size1Dim; ++idxD3){ - delete [] this->transferM2L[idxLevel][idxD1][idxD2][idxD3]; - } - //delete [] this->transferM2L[idxLevel][idxD1][idxD2]; - } - //delete [] this->transferM2L[idxLevel][idxD1]; - } - //delete [] this->transferM2L[idxLevel]; - } - //delete [] this->transferM2L; - } - - ////////////////////////////////////////////////////////////////// - // Utils - ////////////////////////////////////////////////////////////////// - - // position_2_r_cos_th_sin_th_ph - Spherical positionTsmphere(const F3DPosition& inVector){ - const FReal x2y2 = (inVector.getX() * inVector.getX()) + (inVector.getY() * inVector.getY()); - - Spherical outSphere; - - outSphere.r = FMath::Sqrt( x2y2 + (inVector.getZ() * inVector.getZ())); - outSphere.phi = FMath::Atan2(inVector.getY(),inVector.getX()); - outSphere.cosTheta = inVector.getZ() / outSphere.r; // cos_th = z/r - outSphere.sinTheta = FMath::Sqrt(x2y2) / outSphere.r; // sin_th = sqrt(x^2 + y^2)/r - - return outSphere; - } - - // associated_Legendre_function_Fill_complete_array_of_values_for_cos - void legendreFunction( const int lmax, const FReal inCosTheta, const FReal inSinTheta, FReal* const outResults ){ - // l=0: results[current++] = 1.0; // P_0^0(cosTheta) = 1 - int idxCurrent = 0; - outResults[idxCurrent++] = 1.0; - - // l=1: - // Compute P_1^{0} using (3) and store it into results_array: - outResults[idxCurrent++] = inCosTheta; - - // Compute P_1^1 using (2 bis) and store it into results_array - const FReal invSinTheta = -inSinTheta; // somx2 => -sinTheta - outResults[idxCurrent++] = invSinTheta; - - // l>1: - int idxCurrent1m = 1; //pointer on P_{l-1}^m P_1^0 - int idxCurrent2m = 0; //pointer on P_{l-2}^m P_0^0 - FReal fact = 3.0; - - // Remark: p_results_array_l_minus_1_m and p_results_array_l_minus_2_m - // just need to be incremented at each iteration. - for(int idxl = 2; idxl <= lmax ; ++idxl ){ - for( int idxm = 0; idxm <= idxl - 2 ; ++idxm , ++idxCurrent , ++idxCurrent1m , ++idxCurrent2m ){ - // Compute P_l^m, l >= m+2, using (1) and store it into results_array: - outResults[idxCurrent] = (inCosTheta * ( 2 * idxl - 1 ) * outResults[idxCurrent1m] - ( idxl + idxm - 1 ) - * outResults[idxCurrent2m] ) / ( idxl - idxm ); - } - // p_results_array_l_minus_1_m now points on P_{l-1}^{l-1} - - // Compute P_l^{l-1} using (3) and store it into ptrResults: - outResults[idxCurrent++] = inCosTheta * ( 2 * idxl - 1 ) * outResults[idxCurrent1m]; - - // Compute P_l^l using (2 bis) and store it into results_array: - outResults[idxCurrent++] = fact * invSinTheta * outResults[idxCurrent1m]; - - fact += 2.0; - ++idxCurrent1m; - } - } - - // spherical_harmonic_Inner - //2.7 these - void harmonicInner(const Spherical& inSphere, FComplexe* const outResults){ - - // p_precomputed_cos_and_sin_array - FComplexe cosSin[FMB_Info_M2L_P + 1]; - - for(int idxl = 0 , idxlMod4 = 0; idxl <= FMB_Info_P ; ++idxl, ++idxlMod4){ - if(idxlMod4 == 4) idxlMod4 = 0; - const FReal angleinter = FReal(idxl) * inSphere.phi; - const FReal angle = angleinter + this->PiArrayInner[idxlMod4]; - - cosSin[idxl].setReal( FMath::Sin(angle + FMath::FPiDiv2) ); - cosSin[idxl].setImag( FMath::Sin(angle) ); - - //printf("%d=%e/%e (%d/%e/%e)\n",idxl,cosSin[idxl].getReal(),cosSin[idxl].getImag(),idxl,inSphere.phi,this->PiArrayInner[idxlMod4]); - } - - // p_associated_Legendre_function_Array - FReal legendre[FMB_Info_M2L_exp_size]; - - legendreFunction(FMB_Info_P,inSphere.cosTheta, inSphere.sinTheta, legendre); - /*printf("FMB_Info_M2L_exp_size=%d\n",FMB_Info_M2L_exp_size); - for(int temp = 0 ; temp < FMB_Info_M2L_exp_size ; ++temp){ - printf("%e\n",this->legendre[temp]); - }*/ - - FComplexe* currentResult = outResults; - int idxLegendre = 0;//ptr_associated_Legendre_function_Array - int idxSphereHarmoCoef = 0; - FReal idxRl = 1.0 ; - - //printf("lmax = %d\n",FMB_Info_P); - for(int idxl = 0; idxl <= FMB_Info_P ; ++idxl, idxRl *= inSphere.r){ - for(int idxm = 0 ; idxm <= idxl ; ++idxm, ++currentResult, ++idxSphereHarmoCoef, ++idxLegendre){ - const FReal magnitude = this->sphereHarmoInnerCoef[idxSphereHarmoCoef] * idxRl * legendre[idxLegendre]; - currentResult->setReal( magnitude * cosSin[idxm].getReal() ); - currentResult->setImag( magnitude * cosSin[idxm].getImag() ); - - //printf("l = %d m = %d\n",idxl,idxm); - //printf("magnitude=%e idxRl=%e sphereHarmoInnerCoef=%e real=%e imag=%e\n",magnitude,idxRl,this->sphereHarmoInnerCoef[idxSphereHarmoCoef],currentResult->getReal(),currentResult->getImag()); - } - } - - } - // spherical_harmonic_Outer - void harmonicOuter(const Spherical& inSphere, FComplexe* const outResults){ - // p_precomputed_cos_and_sin_array - FComplexe cosSin[FMB_Info_M2L_P + 1]; - for(int idxl = 0, idxlMod4 = 0; idxl <= FMB_Info_M2L_P ; ++idxl, ++idxlMod4){ - if(idxlMod4 == 4) idxlMod4 = 0; - const FReal angle = idxl * inSphere.phi + this->PiArrayOuter[idxlMod4]; - - cosSin[idxl].setReal( FMath::Sin(angle + FMath::FPiDiv2) ); - cosSin[idxl].setImag( FMath::Sin(angle) ); - - //printf("l=%d \t inSphere.phi=%e \t this->PiArrayOuter[idxlMod4]=%e \t angle=%e \t FMath::Sin(angle + FMath::FPiDiv2)=%e \t FMath::Sin(angle)=%e\n", - // idxl, inSphere.phi, this->PiArrayOuter[idxlMod4], angle, FMath::Sin(angle + FMath::FPiDiv2) , FMath::Sin(angle)); - } - - // p_associated_Legendre_function_Array - FReal legendre[FMB_Info_M2L_exp_size]; - - legendreFunction(FMB_Info_M2L_P,inSphere.cosTheta, inSphere.sinTheta, legendre); - - int idxLegendre = 0; - FComplexe* currentResult = outResults; - - const FReal invR = 1/inSphere.r; - FReal idxRl1 = invR; - for(int idxl = 0 ; idxl <= FMB_Info_M2L_P ; ++idxl, idxRl1 *= invR){ - for(int idxm = 0 ; idxm <= idxl ; ++idxm, ++currentResult, ++idxLegendre){ - const FReal magnitude = this->sphereHarmoOuterCoef[idxl-idxm] * idxRl1 * legendre[idxLegendre]; - currentResult->setReal( magnitude * cosSin[idxm].getReal() ); - currentResult->setImag( magnitude * cosSin[idxm].getImag() ); - //printf("l=%d\t m=%d\t idxRl1=%e\t magnitude=%e\n",idxl,idxm,idxRl1,magnitude); - //printf("l=%d\t m=%d\t cosSin[idxm].getReal()=%e\t cosSin[idxm].getImag()=%e\n", - // idxl,idxm,cosSin[idxm].getReal(),cosSin[idxm].getImag()); - } - } - } - - /** spherical_harmonic_Inner_and_theta_derivated - * Returns the value of the partial derivative of the spherical harmonic - *relative to theta. We have for all m such that -(l-1) <= m <= l-1 : - * - *(d H_l^m(theta, phi))/(d theta) - *= (-1)^m sqrt((l-|m|)!/(l+|m|)!) (d P_l^{|m|}(cos theta))/(d theta) e^{i.m.phi} - *= (-1)^m sqrt((l-|m|)!/(l+|m|)!) 1/sqrt{1-cos^2 theta} [l cos theta P_l^{|m|}(cos theta) - (l+|m|) P_{l-1}^{|m|}(cos theta) ] e^{i.m.phi} - *Since theta is in the range [0, Pi], we have: sin theta > 0 and therefore - *sqrt{1-cos^2 theta} = sin theta. Thus: - * - *(d H_l^m(theta, phi))/(d theta) - *= (-1)^m sqrt((l-|m|)!/(l+|m|)!) 1/(sin theta) [l cos theta P_l^{|m|}(cos theta) - (l+|m|) P_{l-1}^{|m|}(cos theta) ] e^{i.m.phi} - *For |m|=l, we have~: - *(d H_l^l(theta, phi))/(d theta) - *= (-1)^m sqrt(1/(2l)!) 1/(sin theta) [l cos theta P_l^l(cos theta) ] e^{i.m.phi} - * - *Remark: for 0<m<=l: - *(d H_l^{-m}(theta, phi))/(d theta) = [(d H_l^{-m}(theta, phi))/(d theta)]* - * - * - * - *Therefore, we have for (d Inner_l^m(r, theta, phi))/(d theta): - * - *|m|<l: (d Inner_l^m(r, theta, phi))/(d theta) = - *(i^m (-1)^l / (l+|m|)!) 1/(sin theta) [l cos theta P_l^{|m|}(cos theta) - (l+|m|) P_{l-1}^{|m|}(cos theta) ] e^{i.m.phi} r^l - *|m|=l: (d Inner_l^m(r, theta, phi))/(d theta) = - *(i^m (-1)^l / (l+|m|)!) 1/(sin theta) [l cos theta P_l^l(cos theta) ] e^{i.m.phi} r^l - * - * - */ - void harmonicInnerThetaDerivated( - const Spherical& inSphere, - FComplexe * results_array, - FComplexe * theta_derivated_results_array - ){ - // p_precomputed_cos_and_sin_array - FComplexe cosSin[FMB_Info_M2L_P + 1]; - - //printf("HarmoInnerTheta \t lmax = %d \t r = %e \t cos_theta = %e \t sin_theta = %e \t phi = %e\n", - // FMB_Info_P,inSphere.r,inSphere.cosTheta,inSphere.sinTheta,inSphere.phi); - - // Initialization of precomputed_cos_and_sin_array: - for(int idxm = 0 , idxmMod4 = 0; idxm <= FMB_Info_P ; ++idxm, ++idxmMod4){ - if(idxmMod4 == 4) idxmMod4 = 0; - const FReal angle = idxm*inSphere.phi + PiArrayInner[idxmMod4]; - cosSin[idxm].setReal(FMath::Sin(angle + FMath::FPiDiv2)); - cosSin[idxm].setImag(FMath::Sin(angle)); - - //printf("l=%d \t inSphere.phi=%e \t this->PiArrayOuter[idxlMod4]=%e \t angle=%e \t FMath::Sin(angle + FMath::FPiDiv2)=%e \t FMath::Sin(angle)=%e\n", - // idxm, inSphere.phi, this->PiArrayInner[idxmMod4], angle, FMath::Sin(angle + FMath::FPiDiv2) , FMath::Sin(angle)); - } - - - // p_associated_Legendre_function_Array - FReal legendre[FMB_Info_M2L_exp_size]; - - // Initialization of associated_Legendre_function_Array: - legendreFunction(FMB_Info_P, inSphere.cosTheta, inSphere.sinTheta, legendre); - - - FComplexe *p_term = results_array; - FComplexe *p_theta_derivated_term = theta_derivated_results_array; - FReal *p_spherical_harmonic_Inner_coefficients_array = sphereHarmoInnerCoef; - FReal *ptr_associated_Legendre_function_Array = legendre; - FReal *start_ptr_associated_Legendre_function_Array = ptr_associated_Legendre_function_Array; - - // r^l - FReal r_l = 1.0; - for (int l = 0 ; l <= FMB_Info_P ; ++l, r_l *= inSphere.r){ - FReal magnitude; - // m<l: - int m = 0; - for(; m < l ; ++m, ++p_term, ++p_theta_derivated_term, ++p_spherical_harmonic_Inner_coefficients_array, ++ptr_associated_Legendre_function_Array){ - magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * (*ptr_associated_Legendre_function_Array); - - // Computation of Inner_l^m(r, theta, phi): - p_term->setReal( magnitude * cosSin[m].getReal()); - p_term->setImag( magnitude * cosSin[m].getImag()); - - /*printf("%d/%d - magnitude=%e ptr_precomputed_cos_and_sin_array real=%e imag=%e p_term real=%e imag=%e\n", - l,m, - magnitude, - cosSin[m].getReal(), - cosSin[m].getImag(), - p_term->getReal(), - p_term->getImag());*/ - /*printf("\t p_spherical_harmonic_Inner_coefficients_array = %e \t ptr_associated_Legendre_function_Array = %e \t r_l = %e\n", - *p_spherical_harmonic_Inner_coefficients_array, - *ptr_associated_Legendre_function_Array, - r_l - );*/ - - // Computation of {\partial Inner_l^m(r, theta, phi)}/{\partial theta}: - magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * ((l*inSphere.cosTheta*(*ptr_associated_Legendre_function_Array) - - (l+m)*(*(start_ptr_associated_Legendre_function_Array + expansion_Redirection_array_for_j[l-1] + m))) / inSphere.sinTheta); - p_theta_derivated_term->setReal(magnitude * cosSin[m].getReal()); - p_theta_derivated_term->setImag(magnitude * cosSin[m].getImag()); - - //printf("magnitude=%e r_l=%e p_spherical_harmonic_Inner_coefficients_array=%e real=%e imag=%e\n", - // magnitude,r_l,*p_spherical_harmonic_Inner_coefficients_array,p_theta_derivated_term->getReal(),p_theta_derivated_term->getImag()); - } - - // m=l: - // Computation of Inner_m^m(r, theta, phi): - magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * (*ptr_associated_Legendre_function_Array); - p_term->setReal(magnitude * cosSin[m].getReal()); - p_term->setImag(magnitude * cosSin[m].getImag()); - - /*printf("%d - magnitude=%e ptr_precomputed_cos_and_sin_array real=%e imag=%e p_term real=%e imag=%e\n", - l, - magnitude, - cosSin[m].getReal(), - cosSin[m].getImag(), - p_term->getReal(), - p_term->getImag());*/ - /*printf("\t p_spherical_harmonic_Inner_coefficients_array = %e \t ptr_associated_Legendre_function_Array = %e \t r_l = %e\n", - *p_spherical_harmonic_Inner_coefficients_array, - *ptr_associated_Legendre_function_Array, - r_l - );*/ - - // Computation of {\partial Inner_m^m(r, theta, phi)}/{\partial theta}: - magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * (m * inSphere.cosTheta * (*ptr_associated_Legendre_function_Array) / inSphere.sinTheta); - p_theta_derivated_term->setReal(magnitude * cosSin[m].getReal()); - p_theta_derivated_term->setImag(magnitude * cosSin[m].getImag()); - - //printf("magnitude=%e r_l=%e p_spherical_harmonic_Inner_coefficients_array=%e real=%e imag=%e\n", - // magnitude,r_l,*p_spherical_harmonic_Inner_coefficients_array,p_theta_derivated_term->getReal(),p_theta_derivated_term->getImag()); - - ++p_term; - ++p_theta_derivated_term; - ++p_spherical_harmonic_Inner_coefficients_array; - ++ptr_associated_Legendre_function_Array; - } - } - - //[fmb] ff_matrix_Convert_exp_2_transfer_M2L_matrix - /*[Blas] void expffmatrix(const FComplexe* transfer_exp, FComplexe* const ff_transfer_matrix){ - FComplexe *p_ff_transfer_matrix = ff_transfer_matrix; - - for( int M = 0; M <= this->FMB_Info_P ; ++M ){ - for(int m = 0; m <= M ; ++m ){ - for(int N = 0; N <= FMB_Info_P ; ++N ){ - for(int n = 0; n <= 2 * N ; ++n , ++p_ff_transfer_matrix ){ - const int k = N - n - m; - if(k < 0){ - const int pow_of_minus_1_k = ((k%2) ? -1 : 1); - p_ff_transfer_matrix->setReal(pow_of_minus_1_k * transfer_exp[ expansion_Redirection_array_for_j[M + N] - k].getReal()); - p_ff_transfer_matrix->setImag((-pow_of_minus_1_k) * transfer_exp[ expansion_Redirection_array_for_j[M + N] - k].getImag()); - } - else{ - int temp = expansion_Redirection_array_for_j[M + N]; - *p_ff_transfer_matrix = transfer_exp[ expansion_Redirection_array_for_j[M + N] + k]; - } - } - } - } - } - }*/ - - ////////////////////////////////////////////////////////////////// - // Precompute - ////////////////////////////////////////////////////////////////// - - // transfer_M2M_Precompute_all_levels - // transfer_L2L_Precompute_all_levels - void precomputeM2M(){ - FReal treeWidthAtLevel = this->treeWidthAtRoot/2; - - for(int idxLevel = 0 ; idxLevel < TreeHeight - 1 ; ++idxLevel ){ - const F3DPosition father(treeWidthAtLevel,treeWidthAtLevel,treeWidthAtLevel); - treeWidthAtLevel /= 2; - - //std::cout << "[precomputeM2M]treeWidthAtLevel=" << treeWidthAtLevel << "\n"; - //printf("\tidxLevel=%d\tFather.x=%e\tFather.y=%e\tFather.z=%e\n",idxLevel,father.getX(),father.getY(),father.getZ()); - - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild ){ - FTreeCoordinate childBox; - childBox.setPositionFromMorton(idxChild,1); - - const F3DPosition M2MVector ( - father.getX() - (treeWidthAtLevel * (1 + (childBox.getX() * 2))), - father.getY() - (treeWidthAtLevel * (1 + (childBox.getY() * 2))), - father.getZ() - (treeWidthAtLevel * (1 + (childBox.getZ() * 2))) - ); - - harmonicInner(positionTsmphere(M2MVector),this->transitionM2M[idxLevel][idxChild]); - - const F3DPosition L2LVector ( - (treeWidthAtLevel * (1 + (childBox.getX() * 2))) - father.getX(), - (treeWidthAtLevel * (1 + (childBox.getY() * 2))) - father.getY(), - (treeWidthAtLevel * (1 + (childBox.getZ() * 2))) - father.getZ() - ); - - harmonicInner(positionTsmphere(L2LVector),this->transitionL2L[idxLevel][idxChild]); - - //printf("[M2M_vector]%d/%d = %e/%e/%e\n", idxLevel , idxChild , M2MVector.getX() , M2MVector.getY() , M2MVector.getZ() ); - //printf("[M2M_vectorSpherical]%d/%d = %e/%e/%e/%e\n", idxLevel , idxChild , sphericalM2M.r , sphericalM2M.cosTheta , sphericalM2M.sinTheta , sphericalM2M.phi ); - //for(int idxExpSize = 0 ; idxExpSize < FMB_Info_exp_size ; ++idxExpSize){ - //std::cout << "transitionL2L[" << idxLevel << "][" << idxChild << "][" << idxExpSize << "]=" << this->transitionL2L[idxLevel][idxChild][idxExpSize].getReal()<<"/"<<this->transitionL2L[idxLevel][idxChild][idxExpSize].getImag()<< "\n"; - //printf("transitionM2M[%d][%d][%d]=%e/%e\n", idxLevel , idxChild , idxExpSize , this->transitionM2M[idxLevel][idxChild][idxExpSize].getReal(),this->transitionM2M[idxLevel][idxChild][idxExpSize].getImag()); - //} - } - } - - } - - - // transfer_M2L_Precompute_all_levels - void precomputeM2L(){ - //[Blas] FComplexe tempComplexe[FMB_Info_M2L_exp_size]; - //printf("FMB_Info.M2L_exp_size = %d\n",FMB_Info_M2L_exp_size); - - FReal treeWidthAtLevel = this->treeWidthAtRoot; - for(int idxLevel = 0 ; idxLevel < TreeHeight ; ++idxLevel ){ - //printf("level = %d \t width = %lf\n",idxLevel,treeWidthAtLevel); - for( int idxd1 = 0; idxd1 < this->size1Dim ; ++idxd1 ){ - - for( int idxd2 = 0; idxd2 < this->size1Dim ; ++idxd2 ){ - - for( int idxd3 = 0; idxd3 < this->size1Dim ; ++idxd3 ){ - const long x = idxd1 - this->halphSize1Dim; - const long y = idxd2 - this->halphSize1Dim; - const long z = idxd3 - this->halphSize1Dim; - - //printf("x=%ld \t y=%ld \t z=%ld\n",x,y,z); - - if( ( x*x + y*y + z*z ) >= ( 3*FMB_Info_ws*FMB_Info_ws + 0.1 ) ){ - const F3DPosition relativePos( x*treeWidthAtLevel , y*treeWidthAtLevel , z*treeWidthAtLevel ); - - // Not blas so - //printf("transferM2L[%d][%d][%d][%d]\n", idxLevel, idxd1, idxd2, idxd3); - harmonicOuter(positionTsmphere(relativePos),this->transferM2L[idxLevel][idxd1][idxd2][idxd3]); - //for(int idxTemp = 0 ; idxTemp < this->FMB_Info_M2L_exp_size ; ++idxTemp){ - // printf("transferM2L[%d][%d][%d][%d][%d]=%e/%e\n", idxLevel, idxd1, idxd2, idxd3, idxTemp, this->transferM2L[idxLevel][idxd1][idxd2][idxd3][idxTemp].getReal(),this->transferM2L[idxLevel][idxd1][idxd2][idxd3][idxTemp].getImag()); - //} - - //[Blas] harmonicOuter(spherical,tempComplexe); - //[Blas] ff_matrix_Convert_exp_2_transfer_M2L_matrix - //[Blas] expffmatrix( tempComplexe , this->transferM2L[idxLevel][idxd1][idxd2][idxd3] ); - } - - } - } - } - treeWidthAtLevel /= 2; - } - } - - void buildPrecompute(){ - expansion_Redirection_array_for_j_Initialize(); - sphericalHarmonicInitialize(); - transferAllocate(); - - precomputeM2M(); - precomputeM2L(); - } - - /** Forbiden copy operator */ - FFmbKernels& operator=(const FFmbKernels&){ return *this; } - -public: - FFmbKernels(const FReal inTreeWidth, const bool inUseMutual = false) : - treeWidthAtRoot(inTreeWidth), UseMutual(inUseMutual) { - buildPrecompute(); - } - - FFmbKernels(const FFmbKernels& other) - : treeWidthAtRoot(other.treeWidthAtRoot), UseMutual(other.UseMutual) { - buildPrecompute(); - } - - virtual void init(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - /** Default destructor */ - virtual ~FFmbKernels(){ - transferDeallocate(); - } - - - ///////////////////////////////////////////////////////////////////////////////// - // Upward - ///////////////////////////////////////////////////////////////////////////////// - - /** OK! - * expansion_P2M_add - * Multipole expansion with m charges q_i in Q_i=(rho_i, alpha_i, beta_i) - *whose relative coordinates according to *p_center are: - *Q_i - *p_center = (rho'_i, alpha'_i, beta'_i); - * - *For j=0..P, k=-j..j, we have: - * - *M_j^k = (-1)^j { sum{i=1..m} q_i Inner_j^k(rho'_i, alpha'_i, beta'_i) } - * - *However the extern loop is over the bodies (i=1..m) in our code and as an - *intern loop we have: j=0..P, k=-j..j - * - *and the potential is then given by: - * - * Phi(x) = sum_{n=0}^{+} sum_{m=-n}^{n} M_n^m O_n^{-m} (x - *p_center) - * - */ - void P2M(CellClass* const inPole, const FList<ParticleClass*>* const inParticles) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - - for(typename FList<ParticleClass*>::ConstBasicIterator iterParticle(*inParticles); - iterParticle.isValide() ; iterParticle.progress()){ - - - //std::cout << "Working on part " << iterParticle.value()->getPhysicalValue() << "\n"; - //F3DPosition tempPos = iterParticle.value()->getPosition() - inPole->getPosition(); - //ok printf("\tpos_rel.x=%e\tpos_rel.y=%e\tpos_rel.z=%e\n",tempPos.getX(),tempPos.getY(),tempPos.getZ()); - //ok printf("\tp_center.x=%e\tp_center.y=%e\tp_center.z=%e\n",inPole->getPosition().getX(),inPole->getPosition().getY(),inPole->getPosition().getZ()); - //ok printf("\tbody.x=%e\tbody.y=%e\tbody.z=%e\n",iterParticle.value()->getPosition().getX(),iterParticle.value()->getPosition().getY(),iterParticle.value()->getPosition().getZ()); - - harmonicInner(positionTsmphere(iterParticle.value()->getPosition() - inPole->getPosition()),current_thread_Y); - - //printf("\tr=%e\tcos_theta=%e\tsin_theta=%e\tphi=%e\n",spherical.r,spherical.cosTheta,spherical.sinTheta,spherical.phi); - - FComplexe* p_exp_term = inPole->getMultipole(); - FComplexe* p_Y_term = current_thread_Y; - FReal pow_of_minus_1_j = 1.0;//(-1)^j - const FReal valueParticle = iterParticle.value()->getPhysicalValue(); - - for(int j = 0 ; j <= FMB_Info_P ; ++j, pow_of_minus_1_j = -pow_of_minus_1_j ){ - for(int k = 0 ; k <= j ; ++k, ++p_Y_term, ++p_exp_term){ - p_Y_term->mulRealAndImag( valueParticle * pow_of_minus_1_j ); - (*p_exp_term) += (*p_Y_term); - //printf("\tj=%d\tk=%d\tp_exp_term.real=%e\tp_exp_term.imag=%e\tp_Y_term.real=%e\tp_Y_term.imag=%e\tpow_of_minus_1_j=%e\n", - // j,k,(*p_exp_term).getReal(),(*p_exp_term).getImag(),(*p_Y_term).getReal(),(*p_Y_term).getImag(),pow_of_minus_1_j); - } - } - } - - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - /** - *----------------------------------- - *octree_Upward_pass_internal_cell - *expansion_M2M_add - *----------------------------------- - *We compute the translation of multipole_exp_src from *p_center_of_exp_src to - *p_center_of_exp_target, and add the result to multipole_exp_target. - * - * O_n^l (with n=0..P, l=-n..n) being the former multipole expansion terms - * (whose center is *p_center_of_multipole_exp_src) we have for the new multipole - * expansion terms (whose center is *p_center_of_multipole_exp_target): - - * M_j^k = sum{n=0..j} - * sum{l=-n..n, |k-l|<=j-n} - * O_n^l Inner_{j-n}^{k-l}(rho, alpha, beta) - * - * where (rho, alpha, beta) are the spherical coordinates of the vector : - * p_center_of_multipole_exp_target - *p_center_of_multipole_exp_src - * - * Warning: if j-n < |k-l| we do nothing. - */ - void M2M(CellClass* const FRestrict inPole, const CellClass *const FRestrict *const FRestrict inChild, const int inLevel) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - - // We do NOT have: for(l=n-j+k; l<=j-n+k ;++l){} <=> for(l=-n; l<=n ;++l){if (j-n >= abs(k-l)){}} - // But we have: for(k=MAX(0,n-j+l); k<=j-n+l; ++k){} <=> for(k=0; k<=j; ++k){if (j-n >= abs(k-l)){}} - // (This is not the same as in L2L since the range of values of k is not the same, compared to "n-j" or "j-n".) - // Therefore the loops over n and l are the outmost ones and - // we invert the loop over j with the summation with n: - // for{j=0..P} sum_{n=0}^j <-> sum_{n=0}^P for{j=n..P} - FComplexe* const multipole_exp_target = inPole->getMultipole(); - - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - if(!inChild[idxChild]) continue; - //printf("\tChild %d\n",idxChild); - - const FComplexe* const multipole_exp_src = inChild[idxChild]->getMultipole(); - - const FComplexe* const M2M_transfer = transitionM2M[inLevel][idxChild]; - - for(int n = 0 ; n <= FMB_Info_P ; ++n ){ - // l<0 // (-1)^l - FReal pow_of_minus_1_for_l = ( n % 2 ? -1 : 1); - - // O_n^l : here points on the source multipole expansion term of degree n and order |l| - const FComplexe* p_src_exp_term = multipole_exp_src + expansion_Redirection_array_for_j[n]+n; - //printf("\t[p_src_exp_term] expansion_Redirection_array_for_j[n]=%d\tn=%d\n",expansion_Redirection_array_for_j[n],n); - - int l = -n; - for(; l<0 ; ++l, --p_src_exp_term, pow_of_minus_1_for_l = -pow_of_minus_1_for_l){ - - for(int j = n ; j<= FMB_Info_P ; ++j ){ - // M_j^k - FComplexe *p_target_exp_term = multipole_exp_target + expansion_Redirection_array_for_j[j]; - //printf("\t[p_target_exp_term] expansion_Redirection_array_for_j[j]=%d\n",expansion_Redirection_array_for_j[j]); - // Inner_{j-n}^{k-l} : here points on the M2M transfer function/expansion term of degree n-j and order |k-l| - const FComplexe *p_Inner_term= M2M_transfer + expansion_Redirection_array_for_j[j-n]-l /* k==0 */; - //printf("\t[p_Inner_term] expansion_Redirection_array_for_j[j-n]=%d\tl=%d\n",expansion_Redirection_array_for_j[j-n],-l); - - // since n-j+l<0 - for(int k=0 ; k <= (j-n+l) ; ++k, ++p_target_exp_term, ++p_Inner_term){ // l<0 && k>=0 => k-l>0 - p_target_exp_term->incReal( pow_of_minus_1_for_l * - ((p_src_exp_term->getReal() * p_Inner_term->getReal()) + - (p_src_exp_term->getImag() * p_Inner_term->getImag()))); - p_target_exp_term->incImag( pow_of_minus_1_for_l * - ((p_src_exp_term->getReal() * p_Inner_term->getImag()) - - (p_src_exp_term->getImag() * p_Inner_term->getReal()))); - - //printf("\tp_src_exp_term->getReal()=%e\tp_src_exp_term->getImag()=%e\n", p_src_exp_term->getReal(),p_src_exp_term->getImag()); - //printf("\tp_Inner_term->getReal()=%e\tp_Inner_term->getImag()=%e\n", p_Inner_term->getReal(),p_Inner_term->getImag()); - //printf("\tn[%d]l[%d]j[%d]k[%d] = %e / %e\n",n,l,j,k,p_target_exp_term->getReal(),p_target_exp_term->getImag()); - - } // for k - } // for j - } // for l - - // l>=0 - for(; l <= n ; ++l, ++p_src_exp_term, pow_of_minus_1_for_l = -pow_of_minus_1_for_l){ - - for( int j=n ; j <= FMB_Info_P ; ++j ){ - // (-1)^k - FReal pow_of_minus_1_for_k = ( FMath::Max(0,n-j+l) %2 ? -1 : 1 ); - // M_j^k - FComplexe *p_target_exp_term = multipole_exp_target + expansion_Redirection_array_for_j[j] + FMath::Max(0,n-j+l); - // Inner_{j-n}^{k-l} : here points on the M2M transfer function/expansion term of degree n-j and order |k-l| - const FComplexe *p_Inner_term = M2M_transfer + expansion_Redirection_array_for_j[j-n] + l - FMath::Max(0,n-j+l);// -(k-l) - - int k = FMath::Max(0,n-j+l); - for(; k <= (j-n+l) && (k-l) < 0 ; ++k, ++p_target_exp_term, --p_Inner_term, pow_of_minus_1_for_k = -pow_of_minus_1_for_k){ /* l>=0 && k-l<0 */ - p_target_exp_term->incReal( pow_of_minus_1_for_k * pow_of_minus_1_for_l * - ((p_src_exp_term->getReal() * p_Inner_term->getReal()) + - (p_src_exp_term->getImag() * p_Inner_term->getImag()))); - p_target_exp_term->incImag(pow_of_minus_1_for_k * pow_of_minus_1_for_l * - ((p_src_exp_term->getImag() * p_Inner_term->getReal()) - - (p_src_exp_term->getReal() * p_Inner_term->getImag()))); - //printf("\tn[%d]l[%d]j[%d]k[%d] = %e / %e\n",n,l,j,k,p_target_exp_term->getReal(),p_target_exp_term->getImag()); - - } // for k - - for(; k <= (j - n + l) ; ++k, ++p_target_exp_term, ++p_Inner_term){ // l>=0 && k-l>=0 - p_target_exp_term->incReal( - (p_src_exp_term->getReal() * p_Inner_term->getReal()) - - (p_src_exp_term->getImag() * p_Inner_term->getImag())); - p_target_exp_term->incImag( - (p_src_exp_term->getImag() * p_Inner_term->getReal()) + - (p_src_exp_term->getReal() * p_Inner_term->getImag())); - //printf("\tn[%d]l[%d]j[%d]k[%d] = %e / %e\n",n,l,j,k,p_target_exp_term->getReal(),p_target_exp_term->getImag()); - - } // for k - } // for j - } // for l - } // for n - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - ///////////////////////////////////////////////////////////////////////////////// - // M2L - ///////////////////////////////////////////////////////////////////////////////// - - /** - *------------------ - * expansion_M2L_add - *------------------- - *We compute the conversion of multipole_exp_src in *p_center_of_exp_src to - *a local expansion in *p_center_of_exp_target, and add the result to local_exp_target. - * - *O_n^l (with n=0..P, l=-n..n) being the former multipole expansion terms - *(whose center is *p_center_of_multipole_exp_src) we have for the new local - *expansion terms (whose center is *p_center_of_local_exp_target): - * - *L_j^k = sum{n=0..+} - *sum{l=-n..n} - *O_n^l Outer_{j+n}^{-k-l}(rho, alpha, beta) - * - *where (rho, alpha, beta) are the spherical coordinates of the vector : - *p_center_of_local_exp_src - *p_center_of_multipole_exp_target - * - *Remark: here we have always j+n >= |-k-l| - * - */ - void M2L(CellClass* const FRestrict pole, const CellClass*const FRestrict *const FRestrict distantNeighbors, const int size, const int inLevel) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - FTreeCoordinate coordCenter; - coordCenter.setPositionFromMorton(pole->getMortonIndex(),inLevel); - - for(int idxSize = 0 ; idxSize < size ; ++idxSize){ - FTreeCoordinate coordNeighbors; - coordNeighbors.setPositionFromMorton(distantNeighbors[idxSize]->getMortonIndex(),inLevel); - - // printf("Morton = %lld\n",pole->getMortonIndex()); - //printf("\tMorton Neighbors = %lld\n",distantNeighbors[idxSize]->getMortonIndex()); - //printf("\tidxSize = %d\tleve = %d\tMorton = %lld\n",idxSize,inLevel,distantNeighbors[idxSize]->getMortonIndex()); - - const FComplexe* const M2L_transfer = transferM2L[inLevel] - [(coordCenter.getX()+halphSize1Dim-coordNeighbors.getX())] - [(coordCenter.getY()+halphSize1Dim-coordNeighbors.getY())] - [(coordCenter.getZ()+halphSize1Dim-coordNeighbors.getZ())]; - /*printf("level = %d\tx=%ld\ty=%ld\tz=%ld\n", inLevel, - (coordCenter.getX()-coordNeighbors.getX()), - (coordCenter.getY()-coordNeighbors.getY()), - (coordCenter.getZ()-coordNeighbors.getZ()));*/ - /*printf("M2L_transfer[0]= %e/%e\n",M2L_transfer->getReal(),M2L_transfer->getImag()); - printf("M2L_transfer[1]= %e/%e\n",M2L_transfer[1].getReal(),M2L_transfer[1].getImag()); - printf("M2L_transfer[2]= %e/%e\n",M2L_transfer[2].getReal(),M2L_transfer[2].getImag());*/ - const FComplexe* const multipole_exp_src = distantNeighbors[idxSize]->getMultipole(); - // L_j^k - FComplexe* p_target_exp_term = pole->getLocal(); - int start_for_j = 0; - - // HPMSTART(51, "M2L computation (loops)"); - for (int j = start_for_j ; j <= FMB_Info_P ; ++j){ - - int stop_for_n = FMB_Info_P; - if (FMB_Info_up_to_P_in_M2L){ - stop_for_n = FMB_Info_P - j; - } - - // (-1)^k - FReal pow_of_minus_1_for_k = 1.0; - for (int k = 0 ; k <= j ; ++k, pow_of_minus_1_for_k = -pow_of_minus_1_for_k, ++p_target_exp_term){ - - // (-1)^n - FReal pow_of_minus_1_for_n = 1.0; - for (int n = 0 ; n <= stop_for_n ; ++n, pow_of_minus_1_for_n = -pow_of_minus_1_for_n){ - - // O_n^l : here points on the source multipole expansion term of degree n and order |l| - const FComplexe *p_src_exp_term = multipole_exp_src + expansion_Redirection_array_for_j[n] + n; - // Outer_{j+n}^{-k-l} : here points on the M2L transfer function/expansion term of degree j+n and order |-k-l| - const FComplexe *p_Outer_term = M2L_transfer + expansion_Redirection_array_for_j[n+j] + k+n; - //printf("expansion_Get_p_term(M2L_transfer, n+j, k+n)-M2L_transfer = %d \t(n=%d)\n", - // p_Outer_term-M2L_transfer , n ); - //printf("TRUC = %d\n",expansion_Redirection_array_for_j[n+j] + k+n); - FReal pow_of_minus_1_for_l = pow_of_minus_1_for_n; // (-1)^l - // We start with l=n (and not l=-n) so that we always set p_Outer_term to a correct value in the first loop. - int l=n; - for ( ; l>0 ; --l, pow_of_minus_1_for_l = -pow_of_minus_1_for_l, --p_src_exp_term, --p_Outer_term){ // we have -k-l<0 and l>0 - p_target_exp_term->incReal( pow_of_minus_1_for_l * pow_of_minus_1_for_k * - ((p_src_exp_term->getReal() * p_Outer_term->getReal()) + - (p_src_exp_term->getImag() * p_Outer_term->getImag()))); - p_target_exp_term->incImag( pow_of_minus_1_for_l * pow_of_minus_1_for_k * - ((p_src_exp_term->getImag() * p_Outer_term->getReal()) - - (p_src_exp_term->getReal() * p_Outer_term->getImag()))); - // printf("\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - // p_target_exp_term->getReal(),p_target_exp_term->getImag()); - // printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n", - // p_src_exp_term->getReal(),p_src_exp_term->getImag()); - // printf("\t p_Outer_term->real = %e \t p_Outer_term->imag = %e \n", - // p_Outer_term->getReal(),p_Outer_term->getImag()); - //printf("p_Outer_term-M2L_transfer = %d\n", - // p_Outer_term-M2L_transfer); - } - - for (; l>=-n && -k-l<0 ; --l, pow_of_minus_1_for_l = -pow_of_minus_1_for_l, ++p_src_exp_term, --p_Outer_term){ // we have -k-l<0 and l<=0 - p_target_exp_term->incReal( pow_of_minus_1_for_k * - ((p_src_exp_term->getReal() * p_Outer_term->getReal()) - - (p_src_exp_term->getImag() * p_Outer_term->getImag()))); - p_target_exp_term->decImag( pow_of_minus_1_for_k * - ((p_src_exp_term->getImag() * p_Outer_term->getReal()) + - (p_src_exp_term->getReal() * p_Outer_term->getImag()))); - // printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - // p_target_exp_term->getReal(),p_target_exp_term->getImag()); - // printf("\t\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n", - // p_src_exp_term->getReal(),p_src_exp_term->getImag()); - // printf("\t\t p_Outer_term->real = %e \t p_Outer_term->imag = %e \n", - // p_Outer_term->getReal(),p_Outer_term->getImag()); - } - - for (; l>=-n; --l, pow_of_minus_1_for_l = -pow_of_minus_1_for_l, ++p_src_exp_term, ++p_Outer_term){ // we have -k-l>=0 and l<=0 - p_target_exp_term->incReal( pow_of_minus_1_for_l * - ((p_src_exp_term->getReal() * p_Outer_term->getReal()) + - (p_src_exp_term->getImag() * p_Outer_term->getImag()))); - p_target_exp_term->incImag( pow_of_minus_1_for_l * - ((p_src_exp_term->getReal() * p_Outer_term->getImag()) - - (p_src_exp_term->getImag() * p_Outer_term->getReal()))); - // printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - // p_target_exp_term->getReal(),p_target_exp_term->getImag()); - // printf("\t\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n", - // p_src_exp_term->getReal(),p_src_exp_term->getImag()); - // printf("\t\t p_Outer_term->real = %e \t p_Outer_term->imag = %e \n", - // p_Outer_term->getReal(),p_Outer_term->getImag()); - } - //printf("\tj=%d\tk=%d\tn=%d\tl=%d\n",j,k,n,l); - //printf("\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - // p_target_exp_term->getReal(),p_target_exp_term->getImag()); - } - } - } - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - ///////////////////////////////////////////////////////////////////////////////// - // Downard - ///////////////////////////////////////////////////////////////////////////////// - - /** expansion_L2L_add - *We compute the shift of local_exp_src from *p_center_of_exp_src to - *p_center_of_exp_target, and set the result to local_exp_target. - * - *O_n^l (with n=0..P, l=-n..n) being the former local expansion terms - *(whose center is *p_center_of_exp_src) we have for the new local - *expansion terms (whose center is *p_center_of_exp_target): - * - *L_j^k = sum{n=j..P} - *sum{l=-n..n} - *O_n^l Inner_{n-j}^{l-k}(rho, alpha, beta) - * - *where (rho, alpha, beta) are the spherical coordinates of the vector : - *p_center_of_exp_target - *p_center_of_exp_src - * - *Warning: if |l-k| > n-j, we do nothing. - */ - void L2L(const CellClass* const FRestrict pole, CellClass* FRestrict *const FRestrict child, const int inLevel) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - // if no child at this position - if(!child[idxChild]) continue; - - const FComplexe* const L2L_tranfer = transitionL2L[inLevel][idxChild]; - const FComplexe* const local_exp_src = pole->getLocal(); - FComplexe* const local_exp_target = child[idxChild]->getLocal(); - - //printf("Level %d\n", inLevel); - //printf("Father morton %lld\n", pole->getMortonIndex()); - //printf("Child morton %lld\n", child[idxChild]->getMortonIndex()); - - //printf("local exp target %h\n", local_exp_target); - - // L_j^k - FComplexe* p_target_exp_term = local_exp_target; - for (int j=0 ; j<= FMB_Info_P ; ++j){ - // (-1)^k - FReal pow_of_minus_1_for_k = 1.0; - for (int k=0 ; k <= j ; ++k, pow_of_minus_1_for_k = -pow_of_minus_1_for_k, ++p_target_exp_term){ - for (int n=j; n<=FMB_Info_P;++n){ - // O_n^l : here points on the source multipole expansion term of degree n and order |l| - const FComplexe* p_src_exp_term = local_exp_src + expansion_Redirection_array_for_j[n] + n-j+k; - //printf("expansion_Redirection_array_for_j[n] + n-j+k %d\n", expansion_Redirection_array_for_j[n] + n-j+k); - int l = n-j+k; - // Inner_{n-j}^{l-k} : here points on the L2L transfer function/expansion term of degree n-j and order |l-k| - const FComplexe* p_Inner_term = L2L_tranfer + expansion_Redirection_array_for_j[n-j] + l-k; - - //printf("1\n"); - for ( ; l-k>0; --l, --p_src_exp_term, --p_Inner_term){ /* l>0 && l-k>0 */ - p_target_exp_term->incReal( (p_src_exp_term->getReal() * p_Inner_term->getReal()) - - (p_src_exp_term->getImag() * p_Inner_term->getImag())); - p_target_exp_term->incImag( (p_src_exp_term->getImag() * p_Inner_term->getReal()) + - (p_src_exp_term->getReal() * p_Inner_term->getImag())); - /*printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n", - p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\t p_Inner_term->real = %lf \t p_Inner_term->imag = %lf \n", - p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - p_target_exp_term->getReal(),p_target_exp_term->getImag()); - printf("\tp_target_exp_term = %d\n",p_target_exp_term-local_exp_target);*/ - } - - //printf("2\n"); - // (-1)^l - FReal pow_of_minus_1_for_l = ((l%2) ? -1 : 1); - for (; l>0 && l>=j-n+k; --l, pow_of_minus_1_for_l = -pow_of_minus_1_for_l, --p_src_exp_term, ++p_Inner_term){ /* l>0 && l-k<=0 */ - p_target_exp_term->incReal( pow_of_minus_1_for_l * pow_of_minus_1_for_k * - ((p_src_exp_term->getReal() * p_Inner_term->getReal()) + - (p_src_exp_term->getImag() * p_Inner_term->getImag()))); - p_target_exp_term->incImag( pow_of_minus_1_for_l * pow_of_minus_1_for_k * - ((p_src_exp_term->getImag() * p_Inner_term->getReal()) - - (p_src_exp_term->getReal() * p_Inner_term->getImag()))); - /*printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n", - p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\t p_Inner_term->real = %lf \t p_Inner_term->imag = %lf \n", - p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - p_target_exp_term->getReal(),p_target_exp_term->getImag()); - printf("\tp_target_exp_term = %d\n",p_target_exp_term-local_exp_target);*/ - } - - //printf("3\n"); - // l<=0 && l-k<=0 - for (; l>=j-n+k; --l, ++p_src_exp_term, ++p_Inner_term){ - p_target_exp_term->incReal( pow_of_minus_1_for_k * - ((p_src_exp_term->getReal() * p_Inner_term->getReal()) - - (p_src_exp_term->getImag() * p_Inner_term->getImag()))); - p_target_exp_term->decImag( pow_of_minus_1_for_k * - ((p_src_exp_term->getImag() * p_Inner_term->getReal()) + - (p_src_exp_term->getReal() * p_Inner_term->getImag()))); - /*printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n", - p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\t p_Inner_term->real = %lf \t p_Inner_term->imag = %lf \n", - p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - p_target_exp_term->getReal(),p_target_exp_term->getImag()); - printf("\tj=%d\tk=%d\tn=%d\tl=%d\tpow_of_minus_1_for_k=%e\n",j,k,n,l,pow_of_minus_1_for_k); - printf("\tp_target_exp_term = %d\n",p_target_exp_term-local_exp_target);*/ - } - //printf("\tj=%d\tk=%d\tn=%d\tl=%d\n",j,k,n,l); - //printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - // p_target_exp_term->getReal(),p_target_exp_term->getImag()); - } - } - } - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - - /** bodies_L2P - * expansion_L2P_add_to_force_vector_and_to_potential - * expansion_L2P_add_to_force_vector - * expansion_Evaluate_local_with_Y_already_computed - */ - void L2P(const CellClass* const local, FList<ParticleClass*>* const particles){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - typename FList<ParticleClass*>::BasicIterator iterTarget(*particles); - while( iterTarget.isValide() ){ - //printf("Morton %lld\n",local->getMortonIndex()); - - F3DPosition force_vector_in_local_base; - Spherical spherical; - spherical = positionTsmphere( iterTarget.value()->getPosition() - local->getPosition()); - - /*printf("\t\t bodies_it_Get_p_position(&it) x = %lf \t y = %lf \t z = %lf \n", - (iterTarget.value()->getPosition()).getX(), - (iterTarget.value()->getPosition()).getY(), - (iterTarget.value()->getPosition()).getZ()); - printf("\t\t p_leaf_center x = %lf \t y = %lf \t z = %lf \n", - (local->getPosition()).getX(), - (local->getPosition()).getY(), - (local->getPosition()).getZ());*/ - /*printf("\t\t p_position_to_leaf_center x = %lf \t y = %lf \t z = %lf \n", - (iterTarget.value()->getPosition() - local->getPosition()).getX(), - (iterTarget.value()->getPosition() - local->getPosition()).getY(), - (iterTarget.value()->getPosition() - local->getPosition()).getZ());*/ - /*printf("\t\t phi = %lf \t cos = %lf \t sin = %lf \t r= %lf \n", - spherical.phi,spherical.cosTheta,spherical.sinTheta,spherical.r);*/ - - harmonicInnerThetaDerivated( spherical, current_thread_Y, current_thread_Y_theta_derivated); - - // The maximum degree used here will be P. - const FComplexe* p_Y_term = current_thread_Y+1; - const FComplexe* p_Y_theta_derivated_term = current_thread_Y_theta_derivated+1; - const FComplexe* p_local_exp_term = local->getLocal()+1; - - for (int j = 1 ; j <= FMB_Info_P ; ++j ){ - FComplexe exp_term_aux; - - // k=0: - // F_r: - exp_term_aux.setReal( (p_Y_term->getReal() * p_local_exp_term->getReal()) - (p_Y_term->getImag() * p_local_exp_term->getImag()) ); - exp_term_aux.setImag( (p_Y_term->getReal() * p_local_exp_term->getImag()) + (p_Y_term->getImag() * p_local_exp_term->getReal()) ); - - force_vector_in_local_base.setX( force_vector_in_local_base.getX() + j * exp_term_aux.getReal()); - // F_phi: k=0 => nothing to do for F_phi - // F_theta: - exp_term_aux.setReal( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getReal()) - (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getImag()) ); - exp_term_aux.setImag( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getImag()) + (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getReal()) ); - - force_vector_in_local_base.setY( force_vector_in_local_base.getY() + exp_term_aux.getReal()); - - - /*printf("\t j = %d \t exp_term_aux real = %lf imag = %lf \n", - j, - exp_term_aux.getReal(), - exp_term_aux.getImag());*/ - /*printf("\t\t\t p_Y_theta_derivated_term->getReal = %lf \t p_Y_theta_derivated_term->getImag = %lf \n", - p_Y_theta_derivated_term->getReal(),p_Y_theta_derivated_term->getImag());*/ - //printf("\t\t\t p_local_exp_term->getReal = %lf \t p_local_exp_term->getImag = %lf \n", - // p_local_exp_term->getReal(),p_local_exp_term->getImag()); - //printf("\t\t\t p_Y_term->getReal = %lf \t p_Y_term->getImag = %lf \n",p_Y_term->getReal(),p_Y_term->getImag()); - - //printf("[LOOP1] force_vector_in_local_base x = %lf \t y = %lf \t z = %lf \n", - // force_vector_in_local_base.getX(),force_vector_in_local_base.getY(),force_vector_in_local_base.getZ()); - - - ++p_local_exp_term; - ++p_Y_term; - ++p_Y_theta_derivated_term; - - - // k>0: - for (int k=1; k<=j ;++k, ++p_local_exp_term, ++p_Y_term, ++p_Y_theta_derivated_term){ - // F_r: - - exp_term_aux.setReal( (p_Y_term->getReal() * p_local_exp_term->getReal()) - (p_Y_term->getImag() * p_local_exp_term->getImag()) ); - exp_term_aux.setImag( (p_Y_term->getReal() * p_local_exp_term->getImag()) + (p_Y_term->getImag() * p_local_exp_term->getReal()) ); - - force_vector_in_local_base.setX(force_vector_in_local_base.getX() + 2 * j * exp_term_aux.getReal()); - // F_phi: - force_vector_in_local_base.setZ( force_vector_in_local_base.getZ() - 2 * k * exp_term_aux.getImag()); - // F_theta: - - /*printf("\t\t k = %d \t j = %d \t exp_term_aux real = %e imag = %e \n", - k,j, - exp_term_aux.getReal(), - exp_term_aux.getImag());*/ - //printf("\t\t\t p_Y_term->getReal = %e \t p_Y_term->getImag = %e \n",p_Y_term->getReal(),p_Y_term->getImag()); - //printf("\t\t\t p_local_exp_term->getReal = %e \t p_local_exp_term->getImag = %e \n",p_local_exp_term->getReal(),p_local_exp_term->getImag()); - - exp_term_aux.setReal( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getReal()) - (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getImag()) ); - exp_term_aux.setImag( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getImag()) + (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getReal()) ); - - force_vector_in_local_base.setY(force_vector_in_local_base.getY() + 2 * exp_term_aux.getReal()); - - /*printf("\t\t k = %d \t j = %d \t exp_term_aux real = %lf imag = %lf \n", - k,j, - exp_term_aux.getReal(), - exp_term_aux.getImag());*/ - /*printf("\t\t\t p_Y_theta_derivated_term->getReal = %lf \t p_Y_theta_derivated_term->getImag = %lf \n", - p_Y_theta_derivated_term->getReal(),p_Y_theta_derivated_term->getImag());*/ - /*printf("\t\t\t p_local_exp_term->getReal = %lf \t p_local_exp_term->getImag = %lf \n", - p_local_exp_term->getReal(),p_local_exp_term->getImag());*/ - - /*printf("[LOOP2] force_vector_in_local_base x = %lf \t y = %lf \t z = %lf \n", - force_vector_in_local_base.getX(),force_vector_in_local_base.getY(),force_vector_in_local_base.getZ());*/ - } - } - - /*printf("[END LOOP] force_vector_in_local_base x = %lf \t y = %lf \t z = %lf \n", - force_vector_in_local_base.getX(),force_vector_in_local_base.getY(),force_vector_in_local_base.getZ());*/ - - // We want: - gradient(POTENTIAL_SIGN potential). - // The -(- 1.0) computing is not the most efficient programming ... - //#define FMB_TMP_SIGN -(POTENTIAL_SIGN 1.0) - force_vector_in_local_base.setX( force_vector_in_local_base.getX() * (-1.0) / spherical.r); - force_vector_in_local_base.setY( force_vector_in_local_base.getY() * (-1.0) / spherical.r); - force_vector_in_local_base.setZ( force_vector_in_local_base.getZ() * (-1.0) / (spherical.r * spherical.sinTheta)); - //#undef FMB_TMP_SIGN - - ///////////////////////////////////////////////////////////////////// - - //spherical_position_Set_ph - //FMB_INLINE COORDINATES_T angle_Convert_in_MinusPi_Pi(COORDINATES_T a){ - FReal ph = FMath::Fmod(spherical.phi, 2*FMath::FPi); - if (ph > M_PI) ph -= 2*FMath::FPi; - if (ph < -M_PI + FMath::Epsilon) ph += 2 * FMath::Epsilon; - - //spherical_position_Set_th - FReal th = FMath::Fmod(FMath::ACos(spherical.cosTheta), 2*FMath::FPi); - if (th < 0.0) th += 2*FMath::FPi; - if (th > FMath::FPi){ - th = 2*FMath::FPi - th; - //spherical_position_Set_ph(p, spherical_position_Get_ph(p) + M_PI); - ph = FMath::Fmod(ph + FMath::FPi, 2*FMath::FPi); - if (ph > M_PI) ph -= 2*FMath::FPi; - if (ph < -M_PI + FMath::Epsilon) ph += 2 * FMath::Epsilon; - th = FMath::Fmod(th, 2*FMath::FPi); - if (th > M_PI) th -= 2*FMath::FPi; - if (th < -M_PI + FMath::Epsilon) th += 2 * FMath::Epsilon; - } - //spherical_position_Set_r - FReal rh = spherical.r; - if (spherical.r < 0){ - rh = -spherical.r; - //spherical_position_Set_ph(p, M_PI - spherical_position_Get_th(p)); - ph = FMath::Fmod(FMath::FPi - th, 2*FMath::FPi); - if (ph > M_PI) ph -= 2*FMath::FPi; - if (ph < -M_PI + FMath::Epsilon) ph += 2 * FMath::Epsilon; - //spherical_position_Set_th(p, spherical_position_Get_th(p) + M_PI); - th = FMath::Fmod(th + FMath::FPi, 2*FMath::FPi); - if (th < 0.0) th += 2*FMath::FPi; - if (th > FMath::FPi){ - th = 2*FMath::FPi - th; - //spherical_position_Set_ph(p, spherical_position_Get_ph(p) + M_PI); - ph = FMath::Fmod(ph + FMath::FPi, 2*FMath::FPi); - if (ph > M_PI) ph -= 2*FMath::FPi; - if (ph < -M_PI + FMath::Epsilon) ph += 2 * FMath::Epsilon; - th = FMath::Fmod(th, 2*FMath::FPi); - if (th > M_PI) th -= 2*FMath::FPi; - if (th < -M_PI + FMath::Epsilon) th += 2 * FMath::Epsilon; - } - } - - /*printf("[details] ph = %e , rh = %e , th = %e \n", - ph,rh,th);*/ - - - const FReal cos_theta = FMath::Cos(th); - const FReal cos_phi = FMath::Cos(ph); - const FReal sin_theta = FMath::Sin(th); - const FReal sin_phi = FMath::Sin(ph); - - /*printf("[details] cos_theta = %e \t cos_phi = %e \t sin_theta = %e \t sin_phi = %e \n", - cos_theta, cos_phi, sin_theta, sin_phi);*/ - /*printf("[force_vector_in_local_base] x = %lf \t y = %lf \t z = %lf \n", - force_vector_in_local_base.getX(),force_vector_in_local_base.getY(),force_vector_in_local_base.getZ());*/ - - F3DPosition force_vector_tmp; - - force_vector_tmp.setX( - cos_phi * sin_theta * force_vector_in_local_base.getX() + - cos_phi * cos_theta * force_vector_in_local_base.getY() + - (-sin_phi) * force_vector_in_local_base.getZ()); - - force_vector_tmp.setY( - sin_phi * sin_theta * force_vector_in_local_base.getX() + - sin_phi * cos_theta * force_vector_in_local_base.getY() + - cos_phi * force_vector_in_local_base.getZ()); - - force_vector_tmp.setZ( - cos_theta * force_vector_in_local_base.getX() + - (-sin_theta) * force_vector_in_local_base.getY()); - - /*printf("[force_vector_tmp] = %lf \t y = %lf \t z = %lf \n", - force_vector_tmp.getX(),force_vector_tmp.getY(),force_vector_tmp.getZ());*/ - - ///////////////////////////////////////////////////////////////////// - - //#ifndef _DIRECT_MATRIX_ - // When _DIRECT_MATRIX_ is defined, this multiplication is done in 'leaf_Sum_near_and_far_fields()' - force_vector_tmp *= iterTarget.value()->getPhysicalValue(); - //#endif - - /*printf("[force_vector_tmp] fx = %e \t fy = %e \t fz = %e \n", - force_vector_tmp.getX(),force_vector_tmp.getY(),force_vector_tmp.getZ());*/ - - iterTarget.value()->setForces( iterTarget.value()->getForces() + force_vector_tmp ); - - FReal potential; - expansion_Evaluate_local_with_Y_already_computed(local->getLocal(),&potential); - iterTarget.value()->setPotential(potential); - - /*printf("[END] fx = %e \t fy = %e \t fz = %e \n\n", - iterTarget.value()->getForces().getX(),iterTarget.value()->getForces().getY(),iterTarget.value()->getForces().getZ());*/ - //printf("p_potential = %lf\n", potential); - - iterTarget.progress(); - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - - void expansion_Evaluate_local_with_Y_already_computed(const FComplexe* local_exp, - FReal* const p_result){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - - FReal result = 0.0; - - FComplexe* p_Y_term = current_thread_Y; - for(int j = 0 ; j<= FMB_Info_P ; ++j){ - // k=0 - (*p_Y_term) *= (*local_exp); - result += p_Y_term->getReal(); - //printf("\t\t p_Y_term->real = %e p_Y_term->imag = %e \t local_exp->real = %e local_exp->imag = %e \n", - // p_Y_term->getReal(), p_Y_term->getImag(), local_exp->getReal(), local_exp->getImag()); - ++p_Y_term; - ++local_exp; - - // k>0 - for (int k=1; k<=j ;++k, ++p_Y_term, ++local_exp){ - (*p_Y_term) *= (*local_exp); - result += 2 * p_Y_term->getReal(); - //printf("\t\t p_Y_term->real = %e p_Y_term->imag = %e \t local_exp->real = %e local_exp->imag = %e \n", - // p_Y_term->getReal(), p_Y_term->getImag(), local_exp->getReal(), local_exp->getImag()); - } - } - - *p_result = result; - - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - - void P2P(FList<ParticleClass*>* const FRestrict targets, const FList<ParticleClass*>* const FRestrict sources, - FList<ParticleClass*>* FRestrict const* FRestrict directNeighbors, const int size){ - if(UseMutual) P2P_Mutual(targets,sources,directNeighbors,size); - else P2P_No_Mutual(targets,sources,directNeighbors,size); - } - - /////////////////////////////////////////////////////////////////////////////// - // MUTUAL - Need - /////////////////////////////////////////////////////////////////////////////// - - - /** void bodies_Compute_direct_interaction ( - * bodies_t *FMB_RESTRICT p_b_target, - * bodies_t *FMB_RESTRICT p_b_src, - * bool mutual - * ) - * - */ - void P2P_Mutual(FList<ParticleClass*>* const FRestrict targets, const FList<ParticleClass*>* const FRestrict sources, - FList<ParticleClass*>* FRestrict const* FRestrict directNeighbors, const int size) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - typename FList<ParticleClass*>::BasicIterator iterTarget(*targets); - while( iterTarget.isValide() ){ - - for(int idxDirectNeighbors = 0 ; idxDirectNeighbors < size ; ++idxDirectNeighbors){ - if(directNeighbors[idxDirectNeighbors] < targets){ - typename FList<ParticleClass*>::BasicIterator iterSource(*directNeighbors[idxDirectNeighbors]); - while( iterSource.isValide() ){ - DIRECT_COMPUTATION_MUTUAL_SOFT(&iterTarget.value(), - &iterSource.value()); - iterSource.progress(); - } - } - } - - typename FList<ParticleClass*>::BasicIterator iterSameBox = iterTarget;//(*targets); - iterSameBox.progress(); - while( iterSameBox.isValide() ){ - if(iterSameBox.value() < iterTarget.value()){ - DIRECT_COMPUTATION_MUTUAL_SOFT(&iterTarget.value(), - &iterSameBox.value()); - } - iterSameBox.progress(); - } - - //printf("x = %e \t y = %e \t z = %e \n",iterTarget.value()->getPosition().getX(),iterTarget.value()->getPosition().getY(),iterTarget.value()->getPosition().getZ()); - //printf("\t P2P fx = %e \t fy = %e \t fz = %e \n",iterTarget.value()->getForces().getX(),iterTarget.value()->getForces().getY(),iterTarget.value()->getForces().getZ()); - //printf("\t potential = %e \n",iterTarget.value()->getPotential()); - - iterTarget.progress(); - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - - void DIRECT_COMPUTATION_MUTUAL_SOFT(ParticleClass** const target, ParticleClass** const source){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - const FReal dx = (*target)->getPosition().getX() - (*source)->getPosition().getX(); - const FReal dy = (*target)->getPosition().getY() - (*source)->getPosition().getY(); - const FReal dz = (*target)->getPosition().getZ() - (*source)->getPosition().getZ(); - - FReal inv_square_distance = 1.0/ (dx*dx + dy*dy + dz*dz + FMB_Info_eps_soft_square); - FReal inv_distance = FMath::Sqrt(inv_square_distance); - inv_distance *= (*target)->getPhysicalValue() * (*source)->getPhysicalValue(); - inv_square_distance *= inv_distance; - - (*target)->setForces( - (*target)->getForces().getX() + dx * inv_square_distance, - (*target)->getForces().getY() + dy * inv_square_distance, - (*target)->getForces().getZ() + dz * inv_square_distance - ); - (*target)->setPotential( inv_distance + (*target)->getPotential()); - - (*source)->setForces( - (*source)->getForces().getX() + (-dx) * inv_square_distance, - (*source)->getForces().getY() + (-dy) * inv_square_distance, - (*source)->getForces().getZ() + (-dz) * inv_square_distance - ); - (*source)->setPotential( inv_distance + (*source)->getPotential()); - - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - - /////////////////////////////////////////////////////////////////////////////// - // NO MUTUAL - /////////////////////////////////////////////////////////////////////////////// - - /** void bodies_Compute_direct_interaction ( - * bodies_t *FMB_RESTRICT p_b_target, - * bodies_t *FMB_RESTRICT p_b_src, - * bool mutual - * ) - * - */ - void P2P_No_Mutual(FList<ParticleClass*>* const FRestrict targets, const FList<ParticleClass*>* const FRestrict sources, - FList<ParticleClass*>* FRestrict const* FRestrict directNeighbors, const int size) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - typename FList<ParticleClass*>::BasicIterator iterTarget(*targets); - while( iterTarget.isValide() ){ - - for(int idxDirectNeighbors = 0 ; idxDirectNeighbors < size ; ++idxDirectNeighbors){ - typename FList<ParticleClass*>::ConstBasicIterator iterSource(*directNeighbors[idxDirectNeighbors]); - while( iterSource.isValide() ){ - DIRECT_COMPUTATION_NO_MUTUAL_SOFT(&iterTarget.value(), - iterSource.value()); - iterSource.progress(); - } - } - - typename FList<ParticleClass*>::ConstBasicIterator iterSameBox(*sources); - while( iterSameBox.isValide() ){ - if(iterSameBox.value() != iterTarget.value()){ - DIRECT_COMPUTATION_NO_MUTUAL_SOFT(&iterTarget.value(), - iterSameBox.value()); - } - iterSameBox.progress(); - } - - //printf("x = %e \t y = %e \t z = %e \n",iterTarget.value()->getPosition().getX(),iterTarget.value()->getPosition().getY(),iterTarget.value()->getPosition().getZ()); - //printf("\t P2P fx = %e \t fy = %e \t fz = %e \n",iterTarget.value()->getForces().getX(),iterTarget.value()->getForces().getY(),iterTarget.value()->getForces().getZ()); - //printf("\t potential = %e \n",iterTarget.value()->getPotential()); - - iterTarget.progress(); - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - - void DIRECT_COMPUTATION_NO_MUTUAL_SOFT(ParticleClass** const target, const ParticleClass* const source){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - const FReal dx = (*target)->getPosition().getX() - source->getPosition().getX(); - const FReal dy = (*target)->getPosition().getY() - source->getPosition().getY(); - const FReal dz = (*target)->getPosition().getZ() - source->getPosition().getZ(); - - FReal inv_square_distance = 1.0/ (dx*dx + dy*dy + dz*dz + FMB_Info_eps_soft_square); - FReal inv_distance = FMath::Sqrt(inv_square_distance); - inv_distance *= (*target)->getPhysicalValue() * source->getPhysicalValue(); - inv_square_distance *= inv_distance; - - (*target)->setForces( - (*target)->getForces().getX() + dx * inv_square_distance, - (*target)->getForces().getY() + dy * inv_square_distance, - (*target)->getForces().getZ() + dz * inv_square_distance - ); - - (*target)->setPotential( inv_distance + (*target)->getPotential()); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } -}; - - -template< class ParticleClass, class CellClass, int TreeHeight> -const FReal FFmbKernels<ParticleClass,CellClass,TreeHeight>::PiArrayInner[4] = {0, FMath::FPiDiv2, FMath::FPi, -FMath::FPiDiv2}; - - -template< class ParticleClass, class CellClass, int TreeHeight> -const FReal FFmbKernels<ParticleClass,CellClass,TreeHeight>::PiArrayOuter[4] = {0, -FMath::FPiDiv2, FMath::FPi, FMath::FPiDiv2}; - - - -#endif //FFMBKERNELS_HPP - -// [--LICENSE--] diff --git a/Sources/Fmb/FFmbKernelsBlas.hpp b/Sources/Fmb/FFmbKernelsBlas.hpp deleted file mode 100644 index 339e35f0b..000000000 --- a/Sources/Fmb/FFmbKernelsBlas.hpp +++ /dev/null @@ -1,1448 +0,0 @@ -#ifndef FFMBKERNELSBLAS_HPP -#define FFMBKERNELSBLAS_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FGlobal.hpp" -#include "../Utils/FBlas.hpp" -#include "../Components/FAbstractKernels.hpp" - -#include "../Containers/FTreeCoordinate.hpp" -#include "../Containers/FList.hpp" - -#include "../Utils/F3DPosition.hpp" -#include "../Utils/FComplexe.hpp" -#include "../Utils/FMath.hpp" -#include "../Utils/FTrace.hpp" - -#include <iostream> - - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmbKernelsBlas -* @brief -* Please read the license -* -* This code is coming from the fmb library (see documentation to know more about it). -* It is a copy'n paste file with a few modifications. -* To be able to make link between this file and the originals ones you can -* look to the commentary before function or attributes declarations. -* -* This class is abstract because the fmb's algorithm is able to compute -* forces / potential / both -* So this class is the trunk and defines code used for each 3 computations. -* -* Needs cell to extend {FExtendFmbCell} -*/ -template< class ParticleClass, class CellClass, int TreeHeight> -class FFmbKernelsBlas : public FAbstractKernels<ParticleClass,CellClass, TreeHeight> { -protected: - // _GRAVITATIONAL_ - static const int FMB_Info_eps_soft_square = 1; - - // MUST BE FALSE IN BLAS - static const int FMB_Info_up_to_P_in_M2L = false; - - // Can be FMB_Info_P if user ask to -- if FMB_Info.up_to_P_in_M2L it true - static const int FMB_Info_M2L_P = FMB_Info_up_to_P_in_M2L? FMB_Info_P : 2 * FMB_Info_P; - static const int FMB_Info_M2L_exp_size = ((FMB_Info_M2L_P)+1) * ((FMB_Info_M2L_P)+2) * 0.5; - - // Default value set in main - static const int FMB_Info_ws = 1; - - // INTERACTION_LIST_SIZE_ALONG_1_DIM - static const int size1Dim = (2*(2*(FMB_Info_ws)+1) +1); - // HALF_INTERACTION_LIST_SIZE_ALONG_1_DIM - static const int halphSize1Dim = (2*(FMB_Info_ws)+1); - - // EXPANSION_SIZE(FMB_Info.P) - static const int FMB_Info_exp_size = ((FMB_Info_P)+1) * ((FMB_Info_P)+2) * 0.5; - // NEXP_SIZE(FMB_Info.P) - static const int FMB_Info_nexp_size = (FMB_Info_P + 1) * (FMB_Info_P + 1); - - // Width of the box at the root level - FReal treeWidthAtRoot; - - // transfer_M2M_container size is specific to blas - FComplexe transitionM2M[TreeHeight][8][FMB_Info_nexp_size]; - // transfer_L2L_container - FComplexe transitionL2L[TreeHeight][8][FMB_Info_nexp_size]; - - // transfer_container - FComplexe* transferM2L[TreeHeight][size1Dim][size1Dim][size1Dim]; - - //[OK] spherical_harmonic_Outer_coefficients_array - FReal sphereHarmoOuterCoef[FMB_Info_M2L_P+1]; - //[OK] spherical_harmonic_Inner_coefficients_array - FReal sphereHarmoInnerCoef[FMB_Info_M2L_exp_size]; - - FComplexe current_thread_Y[FMB_Info_exp_size]; - - // p_Y_theta_derivated - FComplexe current_thread_Y_theta_derivated[FMB_Info_exp_size]; - - // pow_of_I_array - static const FReal PiArrayInner[4]; - // pow_of_O_array - static const FReal PiArrayOuter[4]; - - // To store spherical position - struct Spherical { - FReal r, cosTheta, sinTheta, phi; - }; - - int expansion_Redirection_array_for_j[FMB_Info_M2L_P + 1 ]; - - static const int FF_MATRIX_ROW_DIM = FMB_Info_exp_size; - static const int FF_MATRIX_COLUMN_DIM = FMB_Info_nexp_size; - static const int FF_MATRIX_SIZE = long(FF_MATRIX_ROW_DIM) * long(FF_MATRIX_COLUMN_DIM); - - ////////////////////////////////////////////////////////////////// - // Allocation - ////////////////////////////////////////////////////////////////// - - void expansion_Redirection_array_for_j_Initialize() { - for( int h = 0; h <= FMB_Info_M2L_P ; ++h ){ - expansion_Redirection_array_for_j[h] = static_cast<int>( h * ( h + 1 ) * 0.5 ); - } - } - - //spherical_harmonic_Outer_and_Inner_coefficients_array_Initialize - void sphericalHarmonicInitialize(){ - // Outer coefficients: - //std::cout << "sphereHarmoOuterCoef\n"; - FReal factOuter = 1.0; - // in FMB code stoped at <= FMB_Info_M2L_P but this is not sufficient - for(int idxP = 0 ; idxP <= FMB_Info_M2L_P; factOuter *= (++idxP) ){ - this->sphereHarmoOuterCoef[idxP] = factOuter; - //printf("spherical_harmonic_Outer_coefficients_array %e\n",this->sphereHarmoOuterCoef[idxP]); - //printf("fact_l %e\n",factOuter); - //printf("l %d\n",idxP); - } - - // Inner coefficients: - FReal* currentInner = this->sphereHarmoInnerCoef; - FReal factInner = 1.0; - FReal powN1idxP = 1.0; - //std::cout << "sphereHarmoInnerCoef\n"; - for(int idxP = 0 ; idxP <= this->FMB_Info_M2L_P ; factInner *= (++idxP), powN1idxP = -powN1idxP){ - for(int idxMP = 0, fact_l_m = factInner; idxMP <= idxP ; fact_l_m *= idxP+(++idxMP), ++currentInner){ - *currentInner = powN1idxP / fact_l_m; - //std::cout << (*currentInner) << "\n"; - } - } - - //for(int temp = 0 ; temp < 6 ; ++temp){ - // std::cout << this->sphereHarmoInnerCoef[temp] << "\n"; - //} - } - - - // transfer_L2L_Allocate - // transfer_M2M_Allocate - // transfer_M2L_Allocate - void transferAllocate(){ - // M2M L2L - /*this->transitionM2M = new FComplexe**[TreeHeight]; - this->transitionL2L = new FComplexe**[TreeHeight]; - - for(int idxLevel = 0 ; idxLevel < TreeHeight ; ++idxLevel){ - - this->transitionM2M[idxLevel] = new FComplexe*[8]; - this->transitionL2L[idxLevel] = new FComplexe*[8]; - - for(long idxChild = 0; idxChild < 8; ++idxChild){ - this->transitionM2M[idxLevel][idxChild] = new FComplexe[FMB_Info_exp_size]; - this->transitionL2L[idxLevel][idxChild] = new FComplexe[FMB_Info_exp_size]; - } - }*/ - // M2L - //this->transferM2L = new FComplexe****[TreeHeight+1]; - - for(int idxLevel = 0; idxLevel < TreeHeight; ++idxLevel){ - //this->transferM2L[idxLevel] = new FComplexe***[this->size1Dim]; - - for(long idxD1 = 0 ; idxD1 < this->size1Dim; ++idxD1){ - //this->transferM2L[idxLevel][idxD1] = new FComplexe**[this->size1Dim]; - - for(long idxD2 = 0; idxD2 < this->size1Dim; ++idxD2){ - //this->transferM2L[idxLevel][idxD1][idxD2] = new FComplexe*[this->size1Dim]; - - for(long idxD3 = 0; idxD3 < this->size1Dim; ++idxD3){ - const int x = idxD1 - this->halphSize1Dim; - const int y = idxD2 - this->halphSize1Dim; - const int z = idxD3 - this->halphSize1Dim; - - if( ( x*x + y*y + z*z ) >= ( 3*this->FMB_Info_ws*this->FMB_Info_ws + 0.1 ) ){ - //[Blas] this->transferM2L[idxLevel][idxD1][idxD2][idxD3] = new FComplexe[this->FMB_Info_exp_size * this->FMB_Info_nexp_size]; - this->transferM2L[idxLevel][idxD1][idxD2][idxD3] = new FComplexe[this->FF_MATRIX_SIZE]; - } - else { - this->transferM2L[idxLevel][idxD1][idxD2][idxD3] = NULL; - } - } - } - } - } - } - // transfer_L2L_free - // transfer_M2M_free - // transfer_M2L_free - void transferDeallocate(){ - // M2M L2L - /*for(long idxLevel = 0 ; idxLevel < TreeHeight ; ++idxLevel){ - for(long idxChild = 0; idxChild < 8; ++idxChild){ - delete [] this->transitionM2M[idxLevel][idxChild]; - delete [] this->transitionL2L[idxLevel][idxChild]; - } - delete [] this->transitionM2M[idxLevel]; - delete [] transitionL2L[idxLevel]; - } - delete [] this->transitionM2M; - delete [] this->transitionL2L;*/ - // M2L - for(int idxLevel = 0 ; idxLevel < TreeHeight; ++idxLevel){ - for(long idxD1 = 0 ; idxD1 < this->size1Dim ; ++idxD1){ - for(long idxD2 = 0 ; idxD2 < this->size1Dim ; ++idxD2){ - for(long idxD3 = 0 ; idxD3 < this->size1Dim; ++idxD3){ - delete [] this->transferM2L[idxLevel][idxD1][idxD2][idxD3]; - } - //delete [] this->transferM2L[idxLevel][idxD1][idxD2]; - } - //delete [] this->transferM2L[idxLevel][idxD1]; - } - //delete [] this->transferM2L[idxLevel]; - } - //delete [] this->transferM2L; - } - - ////////////////////////////////////////////////////////////////// - // Utils - ////////////////////////////////////////////////////////////////// - - // position_2_r_cos_th_sin_th_ph - Spherical positionTsmphere(const F3DPosition& inVector){ - const FReal x2y2 = (inVector.getX() * inVector.getX()) + (inVector.getY() * inVector.getY()); - - Spherical outSphere; - - outSphere.r = FMath::Sqrt( x2y2 + (inVector.getZ() * inVector.getZ())); - outSphere.phi = FMath::Atan2(inVector.getY(),inVector.getX()); - outSphere.cosTheta = inVector.getZ() / outSphere.r; // cos_th = z/r - outSphere.sinTheta = FMath::Sqrt(x2y2) / outSphere.r; // sin_th = sqrt(x^2 + y^2)/r - - return outSphere; - } - - // associated_Legendre_function_Fill_complete_array_of_values_for_cos - void legendreFunction( const int lmax, const FReal inCosTheta, const FReal inSinTheta, FReal* const outResults ){ - // l=0: results[current++] = 1.0; // P_0^0(cosTheta) = 1 - int idxCurrent = 0; - outResults[idxCurrent++] = 1.0; - - // l=1: - // Compute P_1^{0} using (3) and store it into results_array: - outResults[idxCurrent++] = inCosTheta; - - // Compute P_1^1 using (2 bis) and store it into results_array - const FReal invSinTheta = -inSinTheta; // somx2 => -sinTheta - outResults[idxCurrent++] = invSinTheta; - - // l>1: - int idxCurrent1m = 1; //pointer on P_{l-1}^m P_1^0 - int idxCurrent2m = 0; //pointer on P_{l-2}^m P_0^0 - FReal fact = 3.0; - - // Remark: p_results_array_l_minus_1_m and p_results_array_l_minus_2_m - // just need to be incremented at each iteration. - for(int idxl = 2; idxl <= lmax ; ++idxl ){ - for( int idxm = 0; idxm <= idxl - 2 ; ++idxm , ++idxCurrent , ++idxCurrent1m , ++idxCurrent2m ){ - // Compute P_l^m, l >= m+2, using (1) and store it into results_array: - outResults[idxCurrent] = (inCosTheta * ( 2 * idxl - 1 ) * outResults[idxCurrent1m] - ( idxl + idxm - 1 ) - * outResults[idxCurrent2m] ) / ( idxl - idxm ); - } - // p_results_array_l_minus_1_m now points on P_{l-1}^{l-1} - - // Compute P_l^{l-1} using (3) and store it into ptrResults: - outResults[idxCurrent++] = inCosTheta * ( 2 * idxl - 1 ) * outResults[idxCurrent1m]; - - // Compute P_l^l using (2 bis) and store it into results_array: - outResults[idxCurrent++] = fact * invSinTheta * outResults[idxCurrent1m]; - - fact += 2.0; - ++idxCurrent1m; - } - - //for(int idxprint = 0 ; idxprint <= FMB_Info_M2L_P ; ++idxprint){ - // printf("\t legendre[%d] = %e\n",idxprint ,outResults[idxprint]); - //} - } - - // spherical_harmonic_Inner - //2.7 these - void harmonicInner(const Spherical& inSphere, FComplexe* const outResults){ - // p_precomputed_cos_and_sin_array - FComplexe cosSin[FMB_Info_M2L_P + 1]; - - for(int idxl = 0 , idxlMod4 = 0; idxl <= FMB_Info_P ; ++idxl, ++idxlMod4){ - if(idxlMod4 == 4) idxlMod4 = 0; - const FReal angleinter = FReal(idxl) * inSphere.phi; - const FReal angle = angleinter + this->PiArrayInner[idxlMod4]; - - cosSin[idxl].setReal( FMath::Sin(angle + FMath::FPiDiv2) ); - cosSin[idxl].setImag( FMath::Sin(angle) ); - - /*printf("%d=%.15e/%.15e (angle %.15e=%d * %.15e + %.15e // (%.15e))\n", - idxl,cosSin[idxl].getReal(),cosSin[idxl].getImag(), - angle,idxl,inSphere.phi,this->PiArrayInner[idxlMod4],angleinter);*/ - - /*printf("sin(%.15e) = %.15e\n", - angle + FMath::FPiDiv2,FMath::Sin(angle + FMath::FPiDiv2));*/ - } - - // p_associated_Legendre_function_Array - FReal legendre[FMB_Info_M2L_exp_size]; - legendreFunction(FMB_Info_P,inSphere.cosTheta, inSphere.sinTheta, legendre); - /*printf("FMB_Info_M2L_exp_size=%d\n",FMB_Info_M2L_exp_size); - for(int temp = 0 ; temp < FMB_Info_M2L_exp_size ; ++temp){ - printf("%e\n",this->legendre[temp]); - }*/ - - FComplexe* currentResult = outResults; - int idxLegendre = 0;//ptr_associated_Legendre_function_Array - int idxSphereHarmoCoef = 0; - FReal idxRl = 1.0 ; - - //printf("lmax = %d\n",FMB_Info_P); - for(int idxl = 0; idxl <= FMB_Info_P ; ++idxl, idxRl *= inSphere.r){ - for(int idxm = 0 ; idxm <= idxl ; ++idxm, ++currentResult, ++idxSphereHarmoCoef, ++idxLegendre){ - const FReal magnitude = this->sphereHarmoInnerCoef[idxSphereHarmoCoef] * idxRl * legendre[idxLegendre]; - currentResult->setReal( magnitude * cosSin[idxm].getReal() ); - currentResult->setImag( magnitude * cosSin[idxm].getImag() ); - - //printf("\t\tl = %d m = %d\n",idxl,idxm); - //printf("\t\tmagnitude=%e idxRl=%e sphereHarmoInnerCoef=%e real=%e imag=%e\n",magnitude,idxRl,this->sphereHarmoInnerCoef[idxSphereHarmoCoef],currentResult->getReal(),currentResult->getImag()); - } - } - - } - // spherical_harmonic_Outer - void harmonicOuter(const Spherical& inSphere, FComplexe* const outResults){ - // p_precomputed_cos_and_sin_array - FComplexe cosSin[FMB_Info_M2L_P + 1]; - - for(int idxl = 0, idxlMod4 = 0; idxl <= FMB_Info_M2L_P ; ++idxl, ++idxlMod4){ - if(idxlMod4 == 4) idxlMod4 = 0; - const FReal angle = idxl * inSphere.phi + this->PiArrayOuter[idxlMod4]; - - cosSin[idxl].setReal( FMath::Sin(angle + FMath::FPiDiv2) ); - cosSin[idxl].setImag( FMath::Sin(angle) ); - - //printf("l=%d \t inSphere.phi=%e \t this->PiArray[idxlMod4]=%e \t angle=%e \t FMath::Sin(angle + FMath::FPiDiv2)=%e \t FMath::Sin(angle)=%e\n", - // idxl, inSphere.phi, this->PiArrayOuter[idxlMod4], angle, FMath::Sin(angle + FMath::FPiDiv2) , FMath::Sin(angle)); - } - - // p_associated_Legendre_function_Array - FReal legendre[FMB_Info_M2L_exp_size]; - legendreFunction(FMB_Info_M2L_P,inSphere.cosTheta, inSphere.sinTheta, legendre); - - int idxLegendre = 0; - FComplexe* currentResult = outResults; - - const FReal invR = 1/inSphere.r; - FReal idxRl1 = invR; - for(int idxl = 0 ; idxl <= FMB_Info_M2L_P ; ++idxl, idxRl1 *= invR){ - for(int idxm = 0 ; idxm <= idxl ; ++idxm, ++currentResult, ++idxLegendre){ - const FReal magnitude = this->sphereHarmoOuterCoef[idxl-idxm] * idxRl1 * legendre[idxLegendre]; - currentResult->setReal( magnitude * cosSin[idxm].getReal() ); - currentResult->setImag( magnitude * cosSin[idxm].getImag() ); - //printf("l=%d\t m=%d\t idxRl1=%e\t magnitude=%e\n",idxl,idxm,idxRl1,magnitude); - //printf("l=%d\t m=%d\t cosSin[idxm].getReal()=%e\t cosSin[idxm].getImag()=%e\n", - // idxl,idxm,cosSin[idxm].getReal(),cosSin[idxm].getImag()); - //printf("this->sphereHarmoOuterCoef[idxl-idxm] = %e \t this->legendre[idxLegendre] = %e \n", - // this->sphereHarmoOuterCoef[idxl-idxm], - // this->legendre[idxLegendre]); - - //for(int idxTemp = 0 ; idxTemp <= idxl-idxm ; idxTemp++ ){ - // printf("\t this->sphereHarmoOuterCoef[%d] = %e\n", idxTemp,this->sphereHarmoOuterCoef[idxTemp] ); - //} - } - } - } - - /** spherical_harmonic_Inner_and_theta_derivated - * Returns the value of the partial derivative of the spherical harmonic - *relative to theta. We have for all m such that -(l-1) <= m <= l-1 : - * - *(d H_l^m(theta, phi))/(d theta) - *= (-1)^m sqrt((l-|m|)!/(l+|m|)!) (d P_l^{|m|}(cos theta))/(d theta) e^{i.m.phi} - *= (-1)^m sqrt((l-|m|)!/(l+|m|)!) 1/sqrt{1-cos^2 theta} [l cos theta P_l^{|m|}(cos theta) - (l+|m|) P_{l-1}^{|m|}(cos theta) ] e^{i.m.phi} - *Since theta is in the range [0, Pi], we have: sin theta > 0 and therefore - *sqrt{1-cos^2 theta} = sin theta. Thus: - * - *(d H_l^m(theta, phi))/(d theta) - *= (-1)^m sqrt((l-|m|)!/(l+|m|)!) 1/(sin theta) [l cos theta P_l^{|m|}(cos theta) - (l+|m|) P_{l-1}^{|m|}(cos theta) ] e^{i.m.phi} - *For |m|=l, we have~: - *(d H_l^l(theta, phi))/(d theta) - *= (-1)^m sqrt(1/(2l)!) 1/(sin theta) [l cos theta P_l^l(cos theta) ] e^{i.m.phi} - * - *Remark: for 0<m<=l: - *(d H_l^{-m}(theta, phi))/(d theta) = [(d H_l^{-m}(theta, phi))/(d theta)]* - * - * - * - *Therefore, we have for (d Inner_l^m(r, theta, phi))/(d theta): - * - *|m|<l: (d Inner_l^m(r, theta, phi))/(d theta) = - *(i^m (-1)^l / (l+|m|)!) 1/(sin theta) [l cos theta P_l^{|m|}(cos theta) - (l+|m|) P_{l-1}^{|m|}(cos theta) ] e^{i.m.phi} r^l - *|m|=l: (d Inner_l^m(r, theta, phi))/(d theta) = - *(i^m (-1)^l / (l+|m|)!) 1/(sin theta) [l cos theta P_l^l(cos theta) ] e^{i.m.phi} r^l - * - * - */ - void harmonicInnerThetaDerivated( - const Spherical& inSphere, - FComplexe * results_array, - FComplexe * theta_derivated_results_array - ){ - - //printf("HarmoInnerTheta \t lmax = %d \t r = %e \t cos_theta = %e \t sin_theta = %e \t phi = %e\n", - // FMB_Info_P,inSphere.r,inSphere.cosTheta,inSphere.sinTheta,inSphere.phi); - - // p_precomputed_cos_and_sin_array - FComplexe cosSin[FMB_Info_M2L_P + 1]; - - // Initialization of precomputed_cos_and_sin_array: - for(int idxm = 0 , idxmMod4 = 0; idxm <= FMB_Info_P ; ++idxm, ++idxmMod4){ - if(idxmMod4 == 4) idxmMod4 = 0; - const FReal angle = idxm*inSphere.phi + PiArrayInner[idxmMod4]; - cosSin[idxm].setReal(FMath::Sin(angle + FMath::FPiDiv2)); - cosSin[idxm].setImag(FMath::Sin(angle)); - - //printf("l=%d \t inSphere.phi=%e \t this->PiArrayOuter[idxlMod4]=%e \t angle=%e \t FMath::Sin(angle + FMath::FPiDiv2)=%e \t FMath::Sin(angle)=%e\n", - // idxm, inSphere.phi, this->PiArrayInner[idxmMod4], angle, FMath::Sin(angle + FMath::FPiDiv2) , FMath::Sin(angle)); - } - - // p_associated_Legendre_function_Array - FReal legendre[FMB_Info_M2L_exp_size]; - // Initialization of associated_Legendre_function_Array: - legendreFunction(FMB_Info_P, inSphere.cosTheta, inSphere.sinTheta, legendre); - - - FComplexe *p_term = results_array; - FComplexe *p_theta_derivated_term = theta_derivated_results_array; - FReal *p_spherical_harmonic_Inner_coefficients_array = sphereHarmoInnerCoef; - FReal *ptr_associated_Legendre_function_Array = legendre; - FReal *start_ptr_associated_Legendre_function_Array = ptr_associated_Legendre_function_Array; - - // r^l - FReal r_l = 1.0; - for (int l = 0 ; l <= FMB_Info_P ; ++l, r_l *= inSphere.r){ - FReal magnitude; - // m<l: - int m = 0; - for(; m < l ; ++m, ++p_term, ++p_theta_derivated_term, ++p_spherical_harmonic_Inner_coefficients_array, ++ptr_associated_Legendre_function_Array){ - magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * (*ptr_associated_Legendre_function_Array); - - // Computation of Inner_l^m(r, theta, phi): - p_term->setReal( magnitude * cosSin[m].getReal()); - p_term->setImag( magnitude * cosSin[m].getImag()); - - /*printf("%d/%d - magnitude=%e ptr_precomputed_cos_and_sin_array real=%e imag=%e p_term real=%e imag=%e\n", - l,m, - magnitude, - cosSin[m].getReal(), - cosSin[m].getImag(), - p_term->getReal(), - p_term->getImag());*/ - /*printf("\t p_spherical_harmonic_Inner_coefficients_array = %e \t ptr_associated_Legendre_function_Array = %e \t r_l = %e\n", - *p_spherical_harmonic_Inner_coefficients_array, - *ptr_associated_Legendre_function_Array, - r_l - );*/ - - // Computation of {\partial Inner_l^m(r, theta, phi)}/{\partial theta}: - magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * ((l*inSphere.cosTheta*(*ptr_associated_Legendre_function_Array) - - (l+m)*(*(start_ptr_associated_Legendre_function_Array + expansion_Redirection_array_for_j[l-1] + m))) / inSphere.sinTheta); - p_theta_derivated_term->setReal(magnitude * cosSin[m].getReal()); - p_theta_derivated_term->setImag(magnitude * cosSin[m].getImag()); - - //printf("magnitude=%e r_l=%e p_spherical_harmonic_Inner_coefficients_array=%e real=%e imag=%e\n", - // magnitude,r_l,*p_spherical_harmonic_Inner_coefficients_array,p_theta_derivated_term->getReal(),p_theta_derivated_term->getImag()); - } - - // m=l: - // Computation of Inner_m^m(r, theta, phi): - magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * (*ptr_associated_Legendre_function_Array); - p_term->setReal(magnitude * cosSin[m].getReal()); - p_term->setImag(magnitude * cosSin[m].getImag()); - - /*printf("%d - magnitude=%e ptr_precomputed_cos_and_sin_array real=%e imag=%e p_term real=%e imag=%e\n", - l, - magnitude, - cosSin[m].getReal(), - cosSin[m].getImag(), - p_term->getReal(), - p_term->getImag());*/ - /*printf("\t p_spherical_harmonic_Inner_coefficients_array = %e \t ptr_associated_Legendre_function_Array = %e \t r_l = %e\n", - *p_spherical_harmonic_Inner_coefficients_array, - *ptr_associated_Legendre_function_Array, - r_l - );*/ - - // Computation of {\partial Inner_m^m(r, theta, phi)}/{\partial theta}: - magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * (m * inSphere.cosTheta * (*ptr_associated_Legendre_function_Array) / inSphere.sinTheta); - p_theta_derivated_term->setReal(magnitude * cosSin[m].getReal()); - p_theta_derivated_term->setImag(magnitude * cosSin[m].getImag()); - - //printf("magnitude=%e r_l=%e p_spherical_harmonic_Inner_coefficients_array=%e real=%e imag=%e\n", - // magnitude,r_l,*p_spherical_harmonic_Inner_coefficients_array,p_theta_derivated_term->getReal(),p_theta_derivated_term->getImag()); - - ++p_term; - ++p_theta_derivated_term; - ++p_spherical_harmonic_Inner_coefficients_array; - ++ptr_associated_Legendre_function_Array; - } - } - - ////////////////////////////////////////////////////////////////// - // Precompute - ////////////////////////////////////////////////////////////////// - - // transfer_M2M_Precompute_all_levels - // transfer_L2L_Precompute_all_levels - void precomputeM2M(){ - FReal treeWidthAtLevel = this->treeWidthAtRoot/2; - - for(int idxLevel = 0 ; idxLevel < TreeHeight - 1 ; ++idxLevel ){ - const F3DPosition father(treeWidthAtLevel,treeWidthAtLevel,treeWidthAtLevel); - treeWidthAtLevel /= 2; - - //std::cout << "[precomputeM2M]treeWidthAtLevel=" << treeWidthAtLevel << "\n"; - //printf("\tidxLevel=%d\tFather.x=%e\tFather.y=%e\tFather.z=%e\n",idxLevel,father.getX(),father.getY(),father.getZ()); - - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild ){ - FTreeCoordinate childBox; - childBox.setPositionFromMorton(idxChild,1); - - const F3DPosition M2MVector ( - father.getX() - (treeWidthAtLevel * (1 + (childBox.getX() * 2))), - father.getY() - (treeWidthAtLevel * (1 + (childBox.getY() * 2))), - father.getZ() - (treeWidthAtLevel * (1 + (childBox.getZ() * 2))) - ); - - harmonicInner(positionTsmphere(M2MVector),this->transitionM2M[idxLevel][idxChild]); - - const F3DPosition L2LVector ( - (treeWidthAtLevel * (1 + (childBox.getX() * 2))) - father.getX(), - (treeWidthAtLevel * (1 + (childBox.getY() * 2))) - father.getY(), - (treeWidthAtLevel * (1 + (childBox.getZ() * 2))) - father.getZ() - ); - - harmonicInner(positionTsmphere(L2LVector),this->transitionL2L[idxLevel][idxChild]); - - //printf("[M2M_vector]%d/%d = %e/%e/%e\n", idxLevel , idxChild , M2MVector.getX() , M2MVector.getY() , M2MVector.getZ() ); - //Spherical = positionTsmphere(M2MVector); - //printf("[M2M_vectorSpherical]%d/%d = %e/%e/%e/%e\n", - // idxLevel , idxChild , sphericalM2M.r , sphericalM2M.cosTheta , sphericalM2M.sinTheta , sphericalM2M.phi ); - //for(int idxExpSize = 0 ; idxExpSize < FMB_Info_exp_size ; ++idxExpSize){ - // printf("transitionM2M[%d][%d][%d]=%e/%e\n", idxLevel , idxChild , idxExpSize , this->transitionM2M[idxLevel][idxChild][idxExpSize].getReal(),this->transitionM2M[idxLevel][idxChild][idxExpSize].getImag()); - //} - } - } - } - - - // transfer_M2L_Precompute_all_levels - void precomputeM2L(){ - //[Blas] FComplexe tempComplexe[FMB_Info_M2L_exp_size]; - //printf("FMB_Info.M2L_exp_size = %d\n",FMB_Info_M2L_exp_size); - - FReal treeWidthAtLevel = this->treeWidthAtRoot; - for(int idxLevel = 0 ; idxLevel < TreeHeight ; ++idxLevel ){ - //printf("level = %d \t width = %lf\n",idxLevel,treeWidthAtLevel); - for( int idxd1 = 0; idxd1 < this->size1Dim ; ++idxd1 ){ - - for( int idxd2 = 0; idxd2 < this->size1Dim ; ++idxd2 ){ - - for( int idxd3 = 0; idxd3 < this->size1Dim ; ++idxd3 ){ - const long x = idxd1 - this->halphSize1Dim; - const long y = idxd2 - this->halphSize1Dim; - const long z = idxd3 - this->halphSize1Dim; - - //printf("x=%ld \t y=%ld \t z=%ld\n",x,y,z); - - if( ( x*x + y*y + z*z ) >= ( 3*FMB_Info_ws*FMB_Info_ws + 0.1 ) ){ - const F3DPosition relativePos( x*treeWidthAtLevel , y*treeWidthAtLevel , z*treeWidthAtLevel ); - - - //printf("blas\n"); - //printf("transferM2L[%d][%d][%d][%d]\n", idxLevel, idxd1, idxd2, idxd3); - FComplexe tempComplexe[FMB_Info_M2L_exp_size]; - harmonicOuter(positionTsmphere(relativePos),tempComplexe); - - //ff_matrix_Convert_exp_2_transfer_M2L_matrix - FComplexe* p_ff_transfer_matrix = this->transferM2L[idxLevel][idxd1][idxd2][idxd3]; - - for(int M = 0 ; M <= FMB_Info_P ; ++M){ - for (int m = 0 ; m <= M ; ++m){ - for (int N = 0 ; N <= FMB_Info_P ; ++N){ - for (int n = 0 ; n <= 2*N ; ++n, ++p_ff_transfer_matrix){ - - //printf("M %d N %d n %d p_ff_transfer_matrix %d\n", M,N,n,int(p_ff_transfer_matrix-this->transferM2L[idxLevel][idxd1][idxd2][idxd3])); - - const int k = N-n-m; - if (k < 0){ - //printf("\t expansion_Get_p_term(transfer_exp, M+N, -k) %d\n",expansion_Redirection_array_for_j[M+N] - k); - const int pow_of_minus_1 = ((k%2) ? -1 : 1); - p_ff_transfer_matrix->setReal( pow_of_minus_1 * (tempComplexe + expansion_Redirection_array_for_j[M+N] - k)->getReal()); - p_ff_transfer_matrix->setImag((-pow_of_minus_1) * (tempComplexe + expansion_Redirection_array_for_j[M+N] - k)->getImag()); - } - else{ - //printf("\t expansion_Get_p_term(transfer_exp, M+N, k) %d\n",expansion_Redirection_array_for_j[M+N] + k); - *p_ff_transfer_matrix = *(tempComplexe + expansion_Redirection_array_for_j[M+N] + k); - } - //printf("\t p_ff_transfer_matrix real %e imag %e\n",p_ff_transfer_matrix->getReal(),p_ff_transfer_matrix->getImag()); - } - } - } - } - - //for(int idxTemp = 0 ; idxTemp < this->FMB_Info_M2L_exp_size ; ++idxTemp){ - // printf("transferM2L[%d][%d][%d][%d][%d]=%e/%e\n", idxLevel, idxd1, idxd2, idxd3, idxTemp, tempComplexe[idxTemp].getReal(),tempComplexe[idxTemp].getImag()); - //} - } - - } - } - } - treeWidthAtLevel /= 2; - } - } - - void buildPrecompute(){ - expansion_Redirection_array_for_j_Initialize(); - sphericalHarmonicInitialize(); - transferAllocate(); - - precomputeM2M(); - precomputeM2L(); - } - -public: - FFmbKernelsBlas(const FReal inTreeWidth) : - treeWidthAtRoot(inTreeWidth) { - buildPrecompute(); - } - - FFmbKernelsBlas(const FFmbKernelsBlas& other) - : treeWidthAtRoot(other.treeWidthAtRoot) { - buildPrecompute(); - } - - virtual void init(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - /** Default destructor */ - virtual ~FFmbKernelsBlas(){ - transferDeallocate(); - } - - - ///////////////////////////////////////////////////////////////////////////////// - // Upward - ///////////////////////////////////////////////////////////////////////////////// - - /** OK! - * expansion_P2M_add - * Multipole expansion with m charges q_i in Q_i=(rho_i, alpha_i, beta_i) - *whose relative coordinates according to *p_center are: - *Q_i - *p_center = (rho'_i, alpha'_i, beta'_i); - * - *For j=0..P, k=-j..j, we have: - * - *M_j^k = (-1)^j { sum{i=1..m} q_i Inner_j^k(rho'_i, alpha'_i, beta'_i) } - * - *However the extern loop is over the bodies (i=1..m) in our code and as an - *intern loop we have: j=0..P, k=-j..j - * - *and the potential is then given by: - * - * Phi(x) = sum_{n=0}^{+} sum_{m=-n}^{n} M_n^m O_n^{-m} (x - *p_center) - * - */ - void P2M(CellClass* const inPole, const FList<ParticleClass*>* const inParticles) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - - for(typename FList<ParticleClass*>::ConstBasicIterator iterParticle(*inParticles); - iterParticle.isValide() ; iterParticle.progress()){ - - - //std::cout << "Working on part " << iterParticle.value()->getPhysicalValue() << "\n"; - //F3DPosition tempPos = iterParticle.value()->getPosition() - inPole->getPosition(); - //ok printf("\tpos_rel.x=%e\tpos_rel.y=%e\tpos_rel.z=%e\n",tempPos.getX(),tempPos.getY(),tempPos.getZ()); - //ok printf("\tp_center.x=%e\tp_center.y=%e\tp_center.z=%e\n",inPole->getPosition().getX(),inPole->getPosition().getY(),inPole->getPosition().getZ()); - //ok printf("\tbody.x=%e\tbody.y=%e\tbody.z=%e\n",iterParticle.value()->getPosition().getX(),iterParticle.value()->getPosition().getY(),iterParticle.value()->getPosition().getZ()); - - harmonicInner(positionTsmphere(iterParticle.value()->getPosition() - inPole->getPosition()),current_thread_Y); - - //ok printf("\tr=%e\tcos_theta=%e\tsin_theta=%e\tphi=%e\n",spherical.r,spherical.cosTheta,spherical.sinTheta,spherical.phi); - - FComplexe* p_exp_term = inPole->getMultipole(); - FComplexe* p_Y_term = current_thread_Y; - FReal pow_of_minus_1_j = 1.0;//(-1)^j - const FReal valueParticle = iterParticle.value()->getPhysicalValue(); - - for(int j = 0 ; j <= FMB_Info_P ; ++j, pow_of_minus_1_j = -pow_of_minus_1_j ){ - for(int k = 0 ; k <= j ; ++k, ++p_Y_term, ++p_exp_term){ - p_Y_term->mulRealAndImag( valueParticle * pow_of_minus_1_j ); - (*p_exp_term) += (*p_Y_term); - //printf("\tj=%d\tk=%d\tp_exp_term.real=%e\tp_exp_term.imag=%e\tp_Y_term.real=%e\tp_Y_term.imag=%e\tpow_of_minus_1_j=%e\n", - // j,k,(*p_exp_term).getReal(),(*p_exp_term).getImag(),(*p_Y_term).getReal(),(*p_Y_term).getImag(),pow_of_minus_1_j); - } - } - } - - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - /** - *----------------------------------- - *octree_Upward_pass_internal_cell - *expansion_M2M_add - *----------------------------------- - *We compute the translation of multipole_exp_src from *p_center_of_exp_src to - *p_center_of_exp_target, and add the result to multipole_exp_target. - * - * O_n^l (with n=0..P, l=-n..n) being the former multipole expansion terms - * (whose center is *p_center_of_multipole_exp_src) we have for the new multipole - * expansion terms (whose center is *p_center_of_multipole_exp_target): - - * M_j^k = sum{n=0..j} - * sum{l=-n..n, |k-l|<=j-n} - * O_n^l Inner_{j-n}^{k-l}(rho, alpha, beta) - * - * where (rho, alpha, beta) are the spherical coordinates of the vector : - * p_center_of_multipole_exp_target - *p_center_of_multipole_exp_src - * - * Warning: if j-n < |k-l| we do nothing. - */ - void M2M(CellClass* const FRestrict inPole, const CellClass *const FRestrict *const FRestrict inChild, const int inLevel) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - - // We do NOT have: for(l=n-j+k; l<=j-n+k ;++l){} <=> for(l=-n; l<=n ;++l){if (j-n >= abs(k-l)){}} - // But we have: for(k=MAX(0,n-j+l); k<=j-n+l; ++k){} <=> for(k=0; k<=j; ++k){if (j-n >= abs(k-l)){}} - // (This is not the same as in L2L since the range of values of k is not the same, compared to "n-j" or "j-n".) - // Therefore the loops over n and l are the outmost ones and - // we invert the loop over j with the summation with n: - // for{j=0..P} sum_{n=0}^j <-> sum_{n=0}^P for{j=n..P} - FComplexe* const multipole_exp_target = inPole->getMultipole(); - //printf("Morton = %lld\n",inPole->getMortonIndex()); - - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - if(!inChild[idxChild]) continue; - //printf("\tChild %d\n",idxChild); - - const FComplexe* const multipole_exp_src = inChild[idxChild]->getMultipole(); - - const FComplexe* const M2M_transfer = transitionM2M[inLevel][idxChild]; - - for(int n = 0 ; n <= FMB_Info_P ; ++n ){ - // l<0 // (-1)^l - FReal pow_of_minus_1_for_l = ( n % 2 ? -1 : 1); - - // O_n^l : here points on the source multipole expansion term of degree n and order |l| - const FComplexe* p_src_exp_term = multipole_exp_src + expansion_Redirection_array_for_j[n]+n; - //printf("\t[p_src_exp_term] expansion_Redirection_array_for_j[n]=%d\tn=%d\n",expansion_Redirection_array_for_j[n],n); - - int l = -n; - for(; l<0 ; ++l, --p_src_exp_term, pow_of_minus_1_for_l = -pow_of_minus_1_for_l){ - - for(int j = n ; j<= FMB_Info_P ; ++j ){ - // M_j^k - FComplexe *p_target_exp_term = multipole_exp_target + expansion_Redirection_array_for_j[j]; - //printf("\t[p_target_exp_term] expansion_Redirection_array_for_j[j]=%d\n",expansion_Redirection_array_for_j[j]); - // Inner_{j-n}^{k-l} : here points on the M2M transfer function/expansion term of degree n-j and order |k-l| - const FComplexe *p_Inner_term= M2M_transfer + expansion_Redirection_array_for_j[j-n]-l /* k==0 */; - //printf("\t[p_Inner_term] expansion_Redirection_array_for_j[j-n]=%d\tl=%d\n",expansion_Redirection_array_for_j[j-n],-l); - - // since n-j+l<0 - for(int k=0 ; k <= (j-n+l) ; ++k, ++p_target_exp_term, ++p_Inner_term){ // l<0 && k>=0 => k-l>0 - p_target_exp_term->incReal( pow_of_minus_1_for_l * - ((p_src_exp_term->getReal() * p_Inner_term->getReal()) + - (p_src_exp_term->getImag() * p_Inner_term->getImag()))); - p_target_exp_term->incImag( pow_of_minus_1_for_l * - ((p_src_exp_term->getReal() * p_Inner_term->getImag()) - - (p_src_exp_term->getImag() * p_Inner_term->getReal()))); - /*printf("1\n"); - printf("\tp_src_exp_term->dat[REAL]=%e\tp_src_exp_term->dat[IMAG]=%e\n", p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\tp_Inner_term->dat[REAL]=%e\tp_Inner_term->dat[IMAG]=%e\n", p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\tn[%d]l[%d]j[%d]k[%d] = %e / %e\n", - n,l,j,k, - p_target_exp_term->getReal(),p_target_exp_term->getImag());*/ - } // for k - } // for j - } // for l - - // l>=0 - for(; l <= n ; ++l, ++p_src_exp_term, pow_of_minus_1_for_l = -pow_of_minus_1_for_l){ - - for( int j=n ; j <= FMB_Info_P ; ++j ){ - // (-1)^k - FReal pow_of_minus_1_for_k = ( FMath::Max(0,n-j+l) %2 ? -1 : 1 ); - // M_j^k - FComplexe *p_target_exp_term = multipole_exp_target + expansion_Redirection_array_for_j[j] + FMath::Max(0,n-j+l); - // Inner_{j-n}^{k-l} : here points on the M2M transfer function/expansion term of degree n-j and order |k-l| - const FComplexe *p_Inner_term = M2M_transfer + expansion_Redirection_array_for_j[j-n] + l - FMath::Max(0,n-j+l);// -(k-l) - - int k = FMath::Max(0,n-j+l); - for(; k <= (j-n+l) && (k-l) < 0 ; ++k, ++p_target_exp_term, --p_Inner_term, pow_of_minus_1_for_k = -pow_of_minus_1_for_k){ /* l>=0 && k-l<0 */ - p_target_exp_term->incReal( pow_of_minus_1_for_k * pow_of_minus_1_for_l * - ((p_src_exp_term->getReal() * p_Inner_term->getReal()) + - (p_src_exp_term->getImag() * p_Inner_term->getImag()))); - p_target_exp_term->incImag(pow_of_minus_1_for_k * pow_of_minus_1_for_l * - ((p_src_exp_term->getImag() * p_Inner_term->getReal()) - - (p_src_exp_term->getReal() * p_Inner_term->getImag()))); - /*printf("2\n"); - printf("\tp_src_exp_term->dat[REAL]=%e\tp_src_exp_term->dat[IMAG]=%e\n", p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\tp_Inner_term->dat[REAL]=%e\tp_Inner_term->dat[IMAG]=%e\n", p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\tn[%d]l[%d]j[%d]k[%d] = %e / %e\n", - n,l,j,k, - p_target_exp_term->getReal(),p_target_exp_term->getImag());*/ - } // for k - - for(; k <= (j - n + l) ; ++k, ++p_target_exp_term, ++p_Inner_term){ // l>=0 && k-l>=0 - p_target_exp_term->incReal( - (p_src_exp_term->getReal() * p_Inner_term->getReal()) - - (p_src_exp_term->getImag() * p_Inner_term->getImag())); - p_target_exp_term->incImag( - (p_src_exp_term->getImag() * p_Inner_term->getReal()) + - (p_src_exp_term->getReal() * p_Inner_term->getImag())); - /*printf("3\n"); - printf("\tp_src_exp_term->dat[REAL]=%e\tp_src_exp_term->dat[IMAG]=%e\n", p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\tp_Inner_term->dat[REAL]=%e\tp_Inner_term->dat[IMAG]=%e\n", p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\tn[%d]l[%d]j[%d]k[%d] = %e / %e\n", - n,l,j,k, - p_target_exp_term->getReal(),p_target_exp_term->getImag());*/ - - } // for k - } // for j - } // for l - } // for n - } - - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - void convert_exp2nexp_inplace(FComplexe* const exp){ - int j, k; - const int P = FMB_Info_P; - FReal pow_of_minus_1_for_k; - FComplexe* p_exp = NULL; - FComplexe* p_nexp = NULL; - - for (j=P; j>=0; --j){ - /* Position in 'exp': (j*(j+1)*0.5) + k - * Position in 'nexp': j*(j+1) + k - */ - int jj_plus_1 = j*(j+1); - int half_jj_plus_1 = (int) jj_plus_1*0.5; - p_exp = exp + half_jj_plus_1 + j; - p_nexp = exp + jj_plus_1 + j; - - /* Positive (or null) orders: */ - for (k=j; k>=0; --k){ - *p_nexp = *p_exp; - //printf("[%d] real = %e imag %e\n",p_nexp-exp,p_nexp->getReal(),p_nexp->getImag()); - --p_exp; - --p_nexp; - } /* for k */ - - /* Negative orders: */ - p_exp += j+1 + half_jj_plus_1; - p_nexp -= j-1; - for (k= -j, - pow_of_minus_1_for_k = ((j%2) ? -1 : 1); - k<0; - ++k, - pow_of_minus_1_for_k = -pow_of_minus_1_for_k){ - p_nexp->setReal(pow_of_minus_1_for_k * p_exp->getReal()); - p_nexp->setImag((-pow_of_minus_1_for_k) * p_exp->getImag()); - //printf("[%d] real = %e imag %e\n",p_nexp-exp,p_nexp->getReal(),p_nexp->getImag()); - --p_exp; - ++p_nexp; - } /* for k */ - - } /* j */ - } - - ///////////////////////////////////////////////////////////////////////////////// - // M2L - ///////////////////////////////////////////////////////////////////////////////// - /** - *------------------ - * ff_full_matrix_Product - * ff_matrix_Product - * octree_Compute_local_exp_M2L - *------------------- - *We compute the conversion of multipole_exp_src in *p_center_of_exp_src to - *a local expansion in *p_center_of_exp_target, and add the result to local_exp_target. - * - *O_n^l (with n=0..P, l=-n..n) being the former multipole expansion terms - *(whose center is *p_center_of_multipole_exp_src) we have for the new local - *expansion terms (whose center is *p_center_of_local_exp_target): - * - *L_j^k = sum{n=0..+} - *sum{l=-n..n} - *O_n^l Outer_{j+n}^{-k-l}(rho, alpha, beta) - * - *where (rho, alpha, beta) are the spherical coordinates of the vector : - *p_center_of_local_exp_src - *p_center_of_multipole_exp_target - * - *Remark: here we have always j+n >= |-k-l| - * - */ - void M2L(CellClass* const FRestrict pole, const CellClass*const FRestrict *const FRestrict distantNeighbors, const int size, const int inLevel) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - FTreeCoordinate coordCenter; - coordCenter.setPositionFromMorton(pole->getMortonIndex(),inLevel); - - for(int idxSize = 0 ; idxSize < size ; ++idxSize){ - FTreeCoordinate coordNeighbors; - coordNeighbors.setPositionFromMorton(distantNeighbors[idxSize]->getMortonIndex(),inLevel); - - ///printf("Morton = %lld\n",pole->getMortonIndex()); - ///printf("\tMorton Neighbors = %lld\n",distantNeighbors[idxSize]->getMortonIndex()); - //printf("\tidxSize = %d\tleve = %d\tMorton = %lld\n",idxSize,inLevel,distantNeighbors[idxSize]->getMortonIndex()); - - const FComplexe* const transfer_M2L_matrix = transferM2L[inLevel] - [(coordCenter.getX()+halphSize1Dim-coordNeighbors.getX())] - [(coordCenter.getY()+halphSize1Dim-coordNeighbors.getY())] - [(coordCenter.getZ()+halphSize1Dim-coordNeighbors.getZ())]; - ///printf("level = %d\tx=%ld\ty=%ld\tz=%ld\n", inLevel, - /// (coordCenter.getX()-coordNeighbors.getX()), - /// (coordCenter.getY()-coordNeighbors.getY()), - /// (coordCenter.getZ()-coordNeighbors.getZ())); - /*printf("M2L_transfer[0]= %e/%e\n",M2L_transfer->getReal(),M2L_transfer->getImag()); - printf("M2L_transfer[1]= %e/%e\n",M2L_transfer[1].getReal(),M2L_transfer[1].getImag()); - printf("M2L_transfer[2]= %e/%e\n",M2L_transfer[2].getReal(),M2L_transfer[2].getImag());*/ - const FComplexe* const multipole_exp_src = distantNeighbors[idxSize]->getMultipole(); - FComplexe* p_target_exp_term = pole->getLocal(); - - //ff_full_matrix_Product - FReal alpha_and_beta[2] = {1.0,0.0}; - //FReal beta[2] = {0.0,0.0}; - - FComplexe multipole_exp_src_changed[FF_MATRIX_COLUMN_DIM]; - memcpy(multipole_exp_src_changed,multipole_exp_src,sizeof(FComplexe)*FF_MATRIX_ROW_DIM); - - convert_exp2nexp_inplace(multipole_exp_src_changed); - - ///for(int j = 0 ; j < FF_MATRIX_ROW_DIM ; ++j){ - /// printf("\t\t local_exp[%d] real = %e imag = %e\n", - /// j,p_target_exp_term[j].getReal(),p_target_exp_term[j].getImag()); - ///} - - /*{ - FILE * trans = fopen("trans.dt","r"); - FILE * exp = fopen("exp.dt","r"); - - fread(transfer_M2L_matrix, sizeof(double),FF_MATRIX_ROW_DIM * FF_MATRIX_COLUMN_DIM*2, trans); - fread(multipole_exp_src_changed, sizeof(double), FF_MATRIX_COLUMN_DIM * 2, exp); - - fclose(trans); - fclose(exp); - }*/ - - // c float cblas_cgemv - // z double cblas_zgemv - //zgemv("T", FF_MATRIX_COLUMN_DIM, FF_MATRIX_ROW_DIM, *((dcmplx*) &(alpha_and_beta)), (dcmplx *) (transfer_M2L_matrix), FF_MATRIX_COLUMN_DIM, (dcmplx *) (multipole_exp_src), 1, *((dcmplx *)&(alpha_and_beta)), (dcmplx *) (p_target_exp_term), 1) - //cgemv("T", FF_MATRIX_COLUMN_DIM, FF_MATRIX_ROW_DIM, *((scmplx*) &(alpha_and_beta)), (scmplx *) (transfer_M2L_matrix), FF_MATRIX_COLUMN_DIM, (scmplx *) (multipole_exp_src), 1, *((scmplx *)&(alpha_and_beta)), (scmplx *) (p_target_exp_term), 1); - cblas_gemv<FReal>(CblasColMajor, CblasTrans, FF_MATRIX_COLUMN_DIM, FF_MATRIX_ROW_DIM, - alpha_and_beta, transfer_M2L_matrix, - FF_MATRIX_COLUMN_DIM,multipole_exp_src_changed, 1, - alpha_and_beta, p_target_exp_term, 1); - //cblas_zgemv(CblasColMajor, CblasTrans, FF_MATRIX_COLUMN_DIM, FF_MATRIX_ROW_DIM, (void *) &(alpha_and_beta), (void *) (transfer_M2L_matrix), FF_MATRIX_COLUMN_DIM, (void *) (multipole_exp_src), 1, (void *) &(alpha_and_beta), (void *) (p_target_exp_term), 1); - - ///printf("FF_MATRIX_COLUMN_DIM = %d, FF_MATRIX_ROW_DIM = %d\n", - /// FF_MATRIX_COLUMN_DIM,FF_MATRIX_ROW_DIM); - - ///printf("CblasColMajor = %d, CblasTrans = %d\n", - /// CblasColMajor,CblasTrans); - - /*for(int j = 0 ; j < FF_MATRIX_ROW_DIM * FF_MATRIX_COLUMN_DIM; ++j){ - printf("\t transfer_M2L_matrix[%d] real = %e imag = %e\n", - j, - //transfer_M2L_matrix[j].getReal(),transfer_M2L_matrix[j].getImag() - ((const FReal*)(const void*)transfer_M2L_matrix)[2*j], - ((const FReal*)(const void*)transfer_M2L_matrix)[2*j + 1] - ); - }*/ - - /*for(int j = 0 ; j < FF_MATRIX_COLUMN_DIM ; ++j){ - printf("\t\t multipole_exp_src[%d] real = %e imag = %e (%p)\n", - j, - //multipole_exp_src_changed[j].getReal(),multipole_exp_src_changed[j].getImag(), - ((FReal*)(void*)multipole_exp_src_changed)[2*j], - ((FReal*)(void*)multipole_exp_src_changed)[2*j + 1], - &multipole_exp_src_changed[j]); - }*/ - /*for(int j = 0 ; j < FF_MATRIX_ROW_DIM ; ++j){ - printf("\t\t local_exp[%d] real = %e imag = %e\n", - j,p_target_exp_term[j].getReal(),p_target_exp_term[j].getImag()); - }*/ - - } - - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - ///////////////////////////////////////////////////////////////////////////////// - // Downard - ///////////////////////////////////////////////////////////////////////////////// - - /** expansion_L2L_add - *We compute the shift of local_exp_src from *p_center_of_exp_src to - *p_center_of_exp_target, and set the result to local_exp_target. - * - *O_n^l (with n=0..P, l=-n..n) being the former local expansion terms - *(whose center is *p_center_of_exp_src) we have for the new local - *expansion terms (whose center is *p_center_of_exp_target): - * - *L_j^k = sum{n=j..P} - *sum{l=-n..n} - *O_n^l Inner_{n-j}^{l-k}(rho, alpha, beta) - * - *where (rho, alpha, beta) are the spherical coordinates of the vector : - *p_center_of_exp_target - *p_center_of_exp_src - * - *Warning: if |l-k| > n-j, we do nothing. - */ - void L2L(const CellClass* const FRestrict pole, CellClass* FRestrict *const FRestrict child, const int inLevel) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - // if no child at this position - if(!child[idxChild]) continue; - - const FComplexe* const L2L_tranfer = transitionL2L[inLevel][idxChild]; - const FComplexe* const local_exp_src = pole->getLocal(); - FComplexe* const local_exp_target = child[idxChild]->getLocal(); - - //printf("Level %d\n", inLevel); - //printf("Father morton %lld\n", pole->getMortonIndex()); - //printf("Child morton %lld\n", child[idxChild]->getMortonIndex()); - - //printf("local exp target %h\n", local_exp_target); - - // L_j^k - FComplexe* p_target_exp_term = local_exp_target; - for (int j=0 ; j<= FMB_Info_P ; ++j){ - // (-1)^k - FReal pow_of_minus_1_for_k = 1.0; - for (int k=0 ; k <= j ; ++k, pow_of_minus_1_for_k = -pow_of_minus_1_for_k, ++p_target_exp_term){ - for (int n=j; n<=FMB_Info_P;++n){ - // O_n^l : here points on the source multipole expansion term of degree n and order |l| - const FComplexe* p_src_exp_term = local_exp_src + expansion_Redirection_array_for_j[n] + n-j+k; - //printf("expansion_Redirection_array_for_j[n] + n-j+k %d\n", expansion_Redirection_array_for_j[n] + n-j+k); - int l = n-j+k; - // Inner_{n-j}^{l-k} : here points on the L2L transfer function/expansion term of degree n-j and order |l-k| - const FComplexe* p_Inner_term = L2L_tranfer + expansion_Redirection_array_for_j[n-j] + l-k; - - //printf("1\n"); - for ( ; l-k>0; --l, --p_src_exp_term, --p_Inner_term){ /* l>0 && l-k>0 */ - p_target_exp_term->incReal( (p_src_exp_term->getReal() * p_Inner_term->getReal()) - - (p_src_exp_term->getImag() * p_Inner_term->getImag())); - p_target_exp_term->incImag( (p_src_exp_term->getImag() * p_Inner_term->getReal()) + - (p_src_exp_term->getReal() * p_Inner_term->getImag())); - /*printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n", - p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\t p_Inner_term->real = %lf \t p_Inner_term->imag = %lf \n", - p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - p_target_exp_term->getReal(),p_target_exp_term->getImag()); - printf("\tp_target_exp_term = %d\n",p_target_exp_term-local_exp_target);*/ - } - - //printf("2\n"); - // (-1)^l - FReal pow_of_minus_1_for_l = ((l%2) ? -1 : 1); - for (; l>0 && l>=j-n+k; --l, pow_of_minus_1_for_l = -pow_of_minus_1_for_l, --p_src_exp_term, ++p_Inner_term){ /* l>0 && l-k<=0 */ - p_target_exp_term->incReal( pow_of_minus_1_for_l * pow_of_minus_1_for_k * - ((p_src_exp_term->getReal() * p_Inner_term->getReal()) + - (p_src_exp_term->getImag() * p_Inner_term->getImag()))); - p_target_exp_term->incImag( pow_of_minus_1_for_l * pow_of_minus_1_for_k * - ((p_src_exp_term->getImag() * p_Inner_term->getReal()) - - (p_src_exp_term->getReal() * p_Inner_term->getImag()))); - /*printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n", - p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\t p_Inner_term->real = %lf \t p_Inner_term->imag = %lf \n", - p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - p_target_exp_term->getReal(),p_target_exp_term->getImag()); - printf("\tp_target_exp_term = %d\n",p_target_exp_term-local_exp_target);*/ - } - - //printf("3\n"); - // l<=0 && l-k<=0 - for (; l>=j-n+k; --l, ++p_src_exp_term, ++p_Inner_term){ - p_target_exp_term->incReal( pow_of_minus_1_for_k * - ((p_src_exp_term->getReal() * p_Inner_term->getReal()) - - (p_src_exp_term->getImag() * p_Inner_term->getImag()))); - p_target_exp_term->decImag( pow_of_minus_1_for_k * - ((p_src_exp_term->getImag() * p_Inner_term->getReal()) + - (p_src_exp_term->getReal() * p_Inner_term->getImag()))); - /*printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n", - p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\t p_Inner_term->real = %lf \t p_Inner_term->imag = %lf \n", - p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - p_target_exp_term->getReal(),p_target_exp_term->getImag()); - printf("\tj=%d\tk=%d\tn=%d\tl=%d\tpow_of_minus_1_for_k=%e\n",j,k,n,l,pow_of_minus_1_for_k); - printf("\tp_target_exp_term = %d\n",p_target_exp_term-local_exp_target);*/ - } - /*printf("\tj=%d\tk=%d\tn=%d\tl=%d\n",j,k,n,l); - printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - p_target_exp_term->getReal(),p_target_exp_term->getImag());*/ - } - } - } - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - - /** bodies_L2P - * expansion_L2P_add_to_force_vector_and_to_potential - * expansion_L2P_add_to_force_vector - * expansion_Evaluate_local_with_Y_already_computed - */ - void L2P(const CellClass* const local, FList<ParticleClass*>* const particles){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - typename FList<ParticleClass*>::BasicIterator iterTarget(*particles); - while( iterTarget.isValide() ){ - //printf("Morton %lld\n",local->getMortonIndex()); - - F3DPosition force_vector_in_local_base; - typename FFmbKernelsBlas<ParticleClass,CellClass,TreeHeight>::Spherical spherical; - spherical = positionTsmphere( iterTarget.value()->getPosition() - local->getPosition()); - - /*printf("\t\t bodies_it_Get_p_position(&it) x = %lf \t y = %lf \t z = %lf \n", - (iterTarget.value()->getPosition()).getX(), - (iterTarget.value()->getPosition()).getY(), - (iterTarget.value()->getPosition()).getZ()); - printf("\t\t p_leaf_center x = %lf \t y = %lf \t z = %lf \n", - (local->getPosition()).getX(), - (local->getPosition()).getY(), - (local->getPosition()).getZ());*/ - /*printf("\t\t p_position_to_leaf_center x = %lf \t y = %lf \t z = %lf \n", - (iterTarget.value()->getPosition() - local->getPosition()).getX(), - (iterTarget.value()->getPosition() - local->getPosition()).getY(), - (iterTarget.value()->getPosition() - local->getPosition()).getZ());*/ - /*printf("\t\t phi = %lf \t cos = %lf \t sin = %lf \t r= %lf \n", - spherical.phi,spherical.cosTheta,spherical.sinTheta,spherical.r);*/ - - harmonicInnerThetaDerivated( spherical, FFmbKernelsBlas<ParticleClass,CellClass,TreeHeight>::current_thread_Y, FFmbKernelsBlas<ParticleClass,CellClass,TreeHeight>::current_thread_Y_theta_derivated); - - // The maximum degree used here will be P. - const FComplexe* p_Y_term = FFmbKernelsBlas<ParticleClass,CellClass,TreeHeight>::current_thread_Y+1; - const FComplexe* p_Y_theta_derivated_term = FFmbKernelsBlas<ParticleClass,CellClass,TreeHeight>::current_thread_Y_theta_derivated+1; - const FComplexe* p_local_exp_term = local->getLocal()+1; - - for (int j = 1 ; j <= FMB_Info_P ; ++j ){ - FComplexe exp_term_aux; - - // k=0: - // F_r: - exp_term_aux.setReal( (p_Y_term->getReal() * p_local_exp_term->getReal()) - (p_Y_term->getImag() * p_local_exp_term->getImag()) ); - exp_term_aux.setImag( (p_Y_term->getReal() * p_local_exp_term->getImag()) + (p_Y_term->getImag() * p_local_exp_term->getReal()) ); - - force_vector_in_local_base.setX( force_vector_in_local_base.getX() + j * exp_term_aux.getReal()); - // F_phi: k=0 => nothing to do for F_phi - // F_theta: - exp_term_aux.setReal( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getReal()) - (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getImag()) ); - exp_term_aux.setImag( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getImag()) + (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getReal()) ); - - force_vector_in_local_base.setY( force_vector_in_local_base.getY() + exp_term_aux.getReal()); - - - /*printf("\t j = %d \t exp_term_aux real = %lf imag = %lf \n", - j, - exp_term_aux.getReal(), - exp_term_aux.getImag());*/ - /*printf("\t\t\t p_Y_theta_derivated_term->getReal = %lf \t p_Y_theta_derivated_term->getImag = %lf \n", - p_Y_theta_derivated_term->getReal(),p_Y_theta_derivated_term->getImag());*/ - //printf("\t\t\t p_local_exp_term->getReal = %lf \t p_local_exp_term->getImag = %lf \n", - // p_local_exp_term->getReal(),p_local_exp_term->getImag()); - //printf("\t\t\t p_Y_term->getReal = %lf \t p_Y_term->getImag = %lf \n",p_Y_term->getReal(),p_Y_term->getImag()); - - //printf("[LOOP1] force_vector_in_local_base x = %lf \t y = %lf \t z = %lf \n", - // force_vector_in_local_base.getX(),force_vector_in_local_base.getY(),force_vector_in_local_base.getZ()); - - - ++p_local_exp_term; - ++p_Y_term; - ++p_Y_theta_derivated_term; - - - // k>0: - for (int k=1; k<=j ;++k, ++p_local_exp_term, ++p_Y_term, ++p_Y_theta_derivated_term){ - // F_r: - - exp_term_aux.setReal( (p_Y_term->getReal() * p_local_exp_term->getReal()) - (p_Y_term->getImag() * p_local_exp_term->getImag()) ); - exp_term_aux.setImag( (p_Y_term->getReal() * p_local_exp_term->getImag()) + (p_Y_term->getImag() * p_local_exp_term->getReal()) ); - - force_vector_in_local_base.setX(force_vector_in_local_base.getX() + 2 * j * exp_term_aux.getReal()); - // F_phi: - force_vector_in_local_base.setZ( force_vector_in_local_base.getZ() - 2 * k * exp_term_aux.getImag()); - // F_theta: - - /*printf("\t\t k = %d \t j = %d \t exp_term_aux real = %e imag = %e \n", - k,j, - exp_term_aux.getReal(), - exp_term_aux.getImag());*/ - //printf("\t\t\t p_Y_term->getReal = %e \t p_Y_term->getImag = %e \n",p_Y_term->getReal(),p_Y_term->getImag()); - //printf("\t\t\t p_local_exp_term->getReal = %e \t p_local_exp_term->getImag = %e \n",p_local_exp_term->getReal(),p_local_exp_term->getImag()); - - exp_term_aux.setReal( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getReal()) - (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getImag()) ); - exp_term_aux.setImag( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getImag()) + (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getReal()) ); - - force_vector_in_local_base.setY(force_vector_in_local_base.getY() + 2 * exp_term_aux.getReal()); - - /*printf("\t\t k = %d \t j = %d \t exp_term_aux real = %lf imag = %lf \n", - k,j, - exp_term_aux.getReal(), - exp_term_aux.getImag());*/ - /*printf("\t\t\t p_Y_theta_derivated_term->getReal = %lf \t p_Y_theta_derivated_term->getImag = %lf \n", - p_Y_theta_derivated_term->getReal(),p_Y_theta_derivated_term->getImag());*/ - /*printf("\t\t\t p_local_exp_term->getReal = %lf \t p_local_exp_term->getImag = %lf \n", - p_local_exp_term->getReal(),p_local_exp_term->getImag());*/ - - /*printf("[LOOP2] force_vector_in_local_base x = %lf \t y = %lf \t z = %lf \n", - force_vector_in_local_base.getX(),force_vector_in_local_base.getY(),force_vector_in_local_base.getZ());*/ - } - } - - /*printf("[END LOOP] force_vector_in_local_base x = %lf \t y = %lf \t z = %lf \n", - force_vector_in_local_base.getX(),force_vector_in_local_base.getY(),force_vector_in_local_base.getZ());*/ - - // We want: - gradient(POTENTIAL_SIGN potential). - // The -(- 1.0) computing is not the most efficient programming ... - //#define FMB_TMP_SIGN -(POTENTIAL_SIGN 1.0) - force_vector_in_local_base.setX( force_vector_in_local_base.getX() * (-1.0) / spherical.r); - force_vector_in_local_base.setY( force_vector_in_local_base.getY() * (-1.0) / spherical.r); - force_vector_in_local_base.setZ( force_vector_in_local_base.getZ() * (-1.0) / (spherical.r * spherical.sinTheta)); - //#undef FMB_TMP_SIGN - - ///////////////////////////////////////////////////////////////////// - - //spherical_position_Set_ph - //FMB_INLINE COORDINATES_T angle_Convert_in_MinusPi_Pi(COORDINATES_T a){ - FReal ph = FMath::Fmod(spherical.phi, 2*FMath::FPi); - if (ph > M_PI) ph -= 2*FMath::FPi; - if (ph < -M_PI + FMath::Epsilon) ph += 2 * FMath::Epsilon; - - //spherical_position_Set_th - FReal th = FMath::Fmod(FMath::ACos(spherical.cosTheta), 2*FMath::FPi); - if (th < 0.0) th += 2*FMath::FPi; - if (th > FMath::FPi){ - th = 2*FMath::FPi - th; - //spherical_position_Set_ph(p, spherical_position_Get_ph(p) + M_PI); - ph = FMath::Fmod(ph + FMath::FPi, 2*FMath::FPi); - if (ph > M_PI) ph -= 2*FMath::FPi; - if (ph < -M_PI + FMath::Epsilon) ph += 2 * FMath::Epsilon; - th = FMath::Fmod(th, 2*FMath::FPi); - if (th > M_PI) th -= 2*FMath::FPi; - if (th < -M_PI + FMath::Epsilon) th += 2 * FMath::Epsilon; - } - //spherical_position_Set_r - FReal rh = spherical.r; - if (spherical.r < 0){ - rh = -spherical.r; - //spherical_position_Set_ph(p, M_PI - spherical_position_Get_th(p)); - ph = FMath::Fmod(FMath::FPi - th, 2*FMath::FPi); - if (ph > M_PI) ph -= 2*FMath::FPi; - if (ph < -M_PI + FMath::Epsilon) ph += 2 * FMath::Epsilon; - //spherical_position_Set_th(p, spherical_position_Get_th(p) + M_PI); - th = FMath::Fmod(th + FMath::FPi, 2*FMath::FPi); - if (th < 0.0) th += 2*FMath::FPi; - if (th > FMath::FPi){ - th = 2*FMath::FPi - th; - //spherical_position_Set_ph(p, spherical_position_Get_ph(p) + M_PI); - ph = FMath::Fmod(ph + FMath::FPi, 2*FMath::FPi); - if (ph > M_PI) ph -= 2*FMath::FPi; - if (ph < -M_PI + FMath::Epsilon) ph += 2 * FMath::Epsilon; - th = FMath::Fmod(th, 2*FMath::FPi); - if (th > M_PI) th -= 2*FMath::FPi; - if (th < -M_PI + FMath::Epsilon) th += 2 * FMath::Epsilon; - } - } - - /*printf("[details] ph = %e , rh = %e , th = %e \n", - ph,rh,th);*/ - - - const FReal cos_theta = FMath::Cos(th); - const FReal cos_phi = FMath::Cos(ph); - const FReal sin_theta = FMath::Sin(th); - const FReal sin_phi = FMath::Sin(ph); - - /*printf("[details] cos_theta = %e \t cos_phi = %e \t sin_theta = %e \t sin_phi = %e \n", - cos_theta, cos_phi, sin_theta, sin_phi);*/ - /*printf("[force_vector_in_local_base] x = %lf \t y = %lf \t z = %lf \n", - force_vector_in_local_base.getX(),force_vector_in_local_base.getY(),force_vector_in_local_base.getZ());*/ - - F3DPosition force_vector_tmp; - - force_vector_tmp.setX( - cos_phi * sin_theta * force_vector_in_local_base.getX() + - cos_phi * cos_theta * force_vector_in_local_base.getY() + - (-sin_phi) * force_vector_in_local_base.getZ()); - - force_vector_tmp.setY( - sin_phi * sin_theta * force_vector_in_local_base.getX() + - sin_phi * cos_theta * force_vector_in_local_base.getY() + - cos_phi * force_vector_in_local_base.getZ()); - - force_vector_tmp.setZ( - cos_theta * force_vector_in_local_base.getX() + - (-sin_theta) * force_vector_in_local_base.getY()); - - /*printf("[force_vector_tmp] = %lf \t y = %lf \t z = %lf \n", - force_vector_tmp.getX(),force_vector_tmp.getY(),force_vector_tmp.getZ());*/ - - ///////////////////////////////////////////////////////////////////// - - //#ifndef _DIRECT_MATRIX_ - // When _DIRECT_MATRIX_ is defined, this multiplication is done in 'leaf_Sum_near_and_far_fields()' - force_vector_tmp *= iterTarget.value()->getPhysicalValue(); - //#endif - - /*printf("[force_vector_tmp] fx = %e \t fy = %e \t fz = %e \n", - force_vector_tmp.getX(),force_vector_tmp.getY(),force_vector_tmp.getZ());*/ - - iterTarget.value()->setForces( iterTarget.value()->getForces() + force_vector_tmp ); - - FReal potential; - expansion_Evaluate_local_with_Y_already_computed(local->getLocal(),&potential); - iterTarget.value()->setPotential(potential); - - /*printf("[END] fx = %e \t fy = %e \t fz = %e \n\n", - iterTarget.value()->getForces().getX(),iterTarget.value()->getForces().getY(),iterTarget.value()->getForces().getZ());*/ - //printf("p_potential = %lf\n", potential); - - iterTarget.progress(); - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - - void expansion_Evaluate_local_with_Y_already_computed(const FComplexe* local_exp, - FReal* const p_result){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - - FReal result = 0.0; - - FComplexe* p_Y_term = FFmbKernelsBlas<ParticleClass,CellClass,TreeHeight>::current_thread_Y; - for(int j = 0 ; j<= FMB_Info_P ; ++j){ - // k=0 - (*p_Y_term) *= (*local_exp); - result += p_Y_term->getReal(); - //printf("\t\t p_Y_term->real = %e p_Y_term->imag = %e \t local_exp->real = %e local_exp->imag = %e \n", - // p_Y_term->getReal(), p_Y_term->getImag(), local_exp->getReal(), local_exp->getImag()); - ++p_Y_term; - ++local_exp; - - // k>0 - for (int k=1; k<=j ;++k, ++p_Y_term, ++local_exp){ - (*p_Y_term) *= (*local_exp); - result += 2 * p_Y_term->getReal(); - //printf("\t\t p_Y_term->real = %e p_Y_term->imag = %e \t local_exp->real = %e local_exp->imag = %e \n", - // p_Y_term->getReal(), p_Y_term->getImag(), local_exp->getReal(), local_exp->getImag()); - } - } - - *p_result = result; - - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - - - - /** void bodies_Compute_direct_interaction ( - * bodies_t *FMB_RESTRICT p_b_target, - * bodies_t *FMB_RESTRICT p_b_src, - * bool mutual - * ) - * - */ - void P2P(FList<ParticleClass*>* const FRestrict targets, const FList<ParticleClass*>* const FRestrict sources, - FList<ParticleClass*>* FRestrict const* FRestrict directNeighbors, const int size) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - typename FList<ParticleClass*>::BasicIterator iterTarget(*targets); - while( iterTarget.isValide() ){ - - for(int idxDirectNeighbors = 0 ; idxDirectNeighbors < size ; ++idxDirectNeighbors){ - typename FList<ParticleClass*>::ConstBasicIterator iterSource(*directNeighbors[idxDirectNeighbors]); - while( iterSource.isValide() ){ - DIRECT_COMPUTATION_NO_MUTUAL_SOFT(&iterTarget.value(), - iterSource.value()); - iterSource.progress(); - } - } - - typename FList<ParticleClass*>::ConstBasicIterator iterSameBox(*sources); - while( iterSameBox.isValide() ){ - if(iterSameBox.value() != iterTarget.value()){ - DIRECT_COMPUTATION_NO_MUTUAL_SOFT(&iterTarget.value(), - iterSameBox.value()); - } - iterSameBox.progress(); - } - - //printf("x = %e \t y = %e \t z = %e \n",iterTarget.value()->getPosition().getX(),iterTarget.value()->getPosition().getY(),iterTarget.value()->getPosition().getZ()); - //printf("\t P2P fx = %e \t fy = %e \t fz = %e \n",iterTarget.value()->getForces().getX(),iterTarget.value()->getForces().getY(),iterTarget.value()->getForces().getZ()); - //printf("\t potential = %e \n",iterTarget.value()->getPotential()); - - iterTarget.progress(); - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - void DIRECT_COMPUTATION_NO_MUTUAL_SOFT(ParticleClass** const target, const ParticleClass* const source){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - const FReal dx = (*target)->getPosition().getX() - source->getPosition().getX(); - const FReal dy = (*target)->getPosition().getY() - source->getPosition().getY(); - const FReal dz = (*target)->getPosition().getZ() - source->getPosition().getZ(); - - FReal inv_square_distance = 1.0/ (dx*dx + dy*dy + dz*dz + FFmbKernelsBlas<ParticleClass,CellClass,TreeHeight>::FMB_Info_eps_soft_square); - FReal inv_distance = FMath::Sqrt(inv_square_distance); - inv_distance *= (*target)->getPhysicalValue() * source->getPhysicalValue(); - inv_square_distance *= inv_distance; - - (*target)->setForces( - (*target)->getForces().getX() + dx * inv_square_distance, - (*target)->getForces().getY() + dy * inv_square_distance, - (*target)->getForces().getZ() + dz * inv_square_distance - ); - - (*target)->setPotential( inv_distance + (*target)->getPotential()); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } -}; - - -template< class ParticleClass, class CellClass, int TreeHeight> -const FReal FFmbKernelsBlas<ParticleClass,CellClass,TreeHeight>::PiArrayInner[4] = {0, FMath::FPiDiv2, FMath::FPi, -FMath::FPiDiv2}; - - -template< class ParticleClass, class CellClass, int TreeHeight> -const FReal FFmbKernelsBlas<ParticleClass,CellClass,TreeHeight>::PiArrayOuter[4] = {0, -FMath::FPiDiv2, FMath::FPi, FMath::FPiDiv2}; - - - -#endif //FFMBKERNELSBLAS_HPP - -// [--LICENSE--] diff --git a/Sources/Fmb/FFmbKernelsBlockBlas.hpp b/Sources/Fmb/FFmbKernelsBlockBlas.hpp deleted file mode 100644 index 5850a4597..000000000 --- a/Sources/Fmb/FFmbKernelsBlockBlas.hpp +++ /dev/null @@ -1,1703 +0,0 @@ -#ifndef FFMBKERNELSBLOCKBLAS_HPP -#define FFMBKERNELSBLOCKBLAS_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "../Utils/FGlobal.hpp" -#include "../Utils/FBlas.hpp" -#include "../Components/FAbstractKernels.hpp" - -#include "../Containers/FTreeCoordinate.hpp" -#include "../Containers/FList.hpp" - -#include "../Utils/F3DPosition.hpp" -#include "../Utils/FComplexe.hpp" -#include "../Utils/FMath.hpp" -#include "../Utils/FTrace.hpp" - -#include "FFmbKernels.hpp" - -#include <iostream> - - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FFmbKernelsBlockBlas -* @brief -* Please read the license -* -* This code is coming from the fmb library (see documentation to know more about it). -* It is a copy'n paste file with a few modifications. -* To be able to make link between this file and the originals ones you can -* look to the commentary before function or attributes declarations. -* -* This class is abstract because the fmb's algorithm is able to compute -* forces / potential / both -* So this class is the trunk and defines code used for each 3 computations. -* -* Needs cell to extend {FExtendFmbCell} -*/ -template< class ParticleClass, class CellClass, int TreeHeight> -class FFmbKernelsBlockBlas : public FAbstractKernels<ParticleClass,CellClass, TreeHeight> { -protected: - // _GRAVITATIONAL_ - static const int FMB_Info_eps_soft_square = 1; - - // MUST BE FALSE IN BLAS - static const int FMB_Info_up_to_P_in_M2L = true; - - // Can be FMB_Info_P if user ask to -- if FMB_Info.up_to_P_in_M2L it true - static const int FMB_Info_M2L_P = FMB_Info_up_to_P_in_M2L? FMB_Info_P : 2 * FMB_Info_P; - static const int FMB_Info_M2L_exp_size = ((FMB_Info_M2L_P)+1) * ((FMB_Info_M2L_P)+2) * 0.5; - - // Default value set in main - static const int FMB_Info_ws = 1; - - // INTERACTION_LIST_SIZE_ALONG_1_DIM - static const int size1Dim = (2*(2*(FMB_Info_ws)+1) +1); - // HALF_INTERACTION_LIST_SIZE_ALONG_1_DIM - static const int halphSize1Dim = (2*(FMB_Info_ws)+1); - - // EXPANSION_SIZE(FMB_Info.P) - static const int FMB_Info_exp_size = ((FMB_Info_P)+1) * ((FMB_Info_P)+2) * 0.5; - // NEXP_SIZE(FMB_Info.P) - static const int FMB_Info_nexp_size = (FMB_Info_P + 1) * (FMB_Info_P + 1); - - // Width of the box at the root level - FReal treeWidthAtRoot; - - // transfer_M2M_container size is specific to blas - FComplexe transitionM2M[TreeHeight][8][FMB_Info_nexp_size]; - // transfer_L2L_container - FComplexe transitionL2L[TreeHeight][8][FMB_Info_nexp_size]; - - struct block_matrix_t { - /* 'P', 'M' and 'N' values for this block: */ - int P_block; - int M_block; - int N_block; - - /* Block matrix values: - * (stored as a one-dimensional array) */ - FComplexe *data; - - /* Info about bssm (biggest square sub-matrix, - * 'square' in the number of blocks, in each dimension, - * it contains): */ - int bssm_row_dim; - int bssm_column_dim; - - - /* Sub blocks: */ - struct block_matrix_t *below; - struct block_matrix_t *right; - - }; - - // transfer_container transfer_M2L_matrix - ff_block_matrix_Allocate_rec - block_matrix_t* transferM2L[TreeHeight][size1Dim][size1Dim][size1Dim]; - - //[OK] spherical_harmonic_Outer_coefficients_array - FReal sphereHarmoOuterCoef[FMB_Info_M2L_P+1]; - //[OK] spherical_harmonic_Inner_coefficients_array - FReal sphereHarmoInnerCoef[FMB_Info_M2L_exp_size]; - - FComplexe current_thread_Y[FMB_Info_exp_size]; - - // p_Y_theta_derivated - FComplexe current_thread_Y_theta_derivated[FMB_Info_exp_size]; - - // pow_of_I_array - static const FReal PiArrayInner[4]; - // pow_of_O_array - static const FReal PiArrayOuter[4]; - - // To store spherical position - struct Spherical { - FReal r, cosTheta, sinTheta, phi; - }; - - int expansion_Redirection_array_for_j[FMB_Info_M2L_P + 1 ]; - - static const int FMB_Info_stop_for_block = 1; - - static const int FF_MATRIX_ROW_DIM = FMB_Info_exp_size; - static const int FF_MATRIX_COLUMN_DIM = FMB_Info_nexp_size; - static const int FF_MATRIX_SIZE = long(FF_MATRIX_ROW_DIM) * long(FF_MATRIX_COLUMN_DIM); - - ////////////////////////////////////////////////////////////////// - // Allocation - ////////////////////////////////////////////////////////////////// - - void expansion_Redirection_array_for_j_Initialize() { - for( int h = 0; h <= FMB_Info_M2L_P ; ++h ){ - expansion_Redirection_array_for_j[h] = static_cast<int>( h * ( h + 1 ) * 0.5 ); - } - } - - //spherical_harmonic_Outer_and_Inner_coefficients_array_Initialize - void sphericalHarmonicInitialize(){ - // Outer coefficients: - //std::cout << "sphereHarmoOuterCoef\n"; - FReal factOuter = 1.0; - // in FMB code stoped at <= FMB_Info_M2L_P but this is not sufficient - for(int idxP = 0 ; idxP <= FMB_Info_M2L_P; factOuter *= (++idxP) ){ - this->sphereHarmoOuterCoef[idxP] = factOuter; - //printf("spherical_harmonic_Outer_coefficients_array %e\n",this->sphereHarmoOuterCoef[idxP]); - //printf("fact_l %e\n",factOuter); - //printf("l %d\n",idxP); - } - - // Inner coefficients: - FReal* currentInner = this->sphereHarmoInnerCoef; - FReal factInner = 1.0; - FReal powN1idxP = 1.0; - //std::cout << "sphereHarmoInnerCoef\n"; - for(int idxP = 0 ; idxP <= this->FMB_Info_M2L_P ; factInner *= (++idxP), powN1idxP = -powN1idxP){ - for(int idxMP = 0, fact_l_m = factInner; idxMP <= idxP ; fact_l_m *= idxP+(++idxMP), ++currentInner){ - *currentInner = powN1idxP / fact_l_m; - //std::cout << (*currentInner) << "\n"; - } - } - - //for(int temp = 0 ; temp < 6 ; ++temp){ - // std::cout << this->sphereHarmoInnerCoef[temp] << "\n"; - //} - } - - - block_matrix_t *ff_block_matrix_Allocate_rec(int M, int N, int P){ - block_matrix_t *res = new block_matrix_t(); - int stop_for_block = FMB_Info_stop_for_block; - - /* Initialize fields of '*res': */ - res->P_block = P; - res->M_block = M; - res->N_block = N; - res->data = NULL; - res->bssm_row_dim = 0; - res->bssm_column_dim = 0; - res->below = NULL; - res->right = NULL; - - - if (P <= stop_for_block){ - /*************** Treat terminal case: ***************/ - /* The 'P+1' bands are stored one after the other, starting from res->data, - * so that the leading dimension is the smallest one. */ - int PP = P+1; - int MM = M+1; - int total = (int) (PP+1) * PP * (PP*PP + 4*MM*PP + 4*PP*N - PP - 4*N +2*MM + 12*MM*N) / 12; - - res->data = new FComplexe[total]; - } - else { - /*************** Recursive case: ***************/ - int q = P/2; - int q_rec = ((P%2 == 0) ? q-1 : q); - - /* Matrix-vector product with the biggest square sub-matrix ('square' in the number of - * blocks, in each dimension, it contains). */ - /* bssm: biggest square sub-matrix */ - - res->bssm_row_dim = (int) ( (q+1) * (q*0.5 + M +1) ); /* sum_{k=0}^{q} (M+k+1) */ - res->bssm_column_dim = (int) ( (q+1) * (2*N + q + 1) ); /* sum_{k=0}^{q} (2*(N+k)+1) */ - - res->data = new FComplexe[res->bssm_row_dim* res->bssm_column_dim]; - - res->below = ff_block_matrix_Allocate_rec(M + q+1, N, q_rec); - res->right = ff_block_matrix_Allocate_rec(M, N + q+1, q_rec); - } - - return res; - } - - // transfer_L2L_Allocate - // transfer_M2M_Allocate - // transfer_M2L_Allocate - void transferAllocate(){ - // M2M L2L - /*this->transitionM2M = new FComplexe**[TreeHeight]; - this->transitionL2L = new FComplexe**[TreeHeight]; - - for(int idxLevel = 0 ; idxLevel < TreeHeight ; ++idxLevel){ - - this->transitionM2M[idxLevel] = new FComplexe*[8]; - this->transitionL2L[idxLevel] = new FComplexe*[8]; - - for(long idxChild = 0; idxChild < 8; ++idxChild){ - this->transitionM2M[idxLevel][idxChild] = new FComplexe[FMB_Info_exp_size]; - this->transitionL2L[idxLevel][idxChild] = new FComplexe[FMB_Info_exp_size]; - } - }*/ - // M2L - //this->transferM2L = new FComplexe****[TreeHeight+1]; - - for(int idxLevel = 0; idxLevel < TreeHeight; ++idxLevel){ - //this->transferM2L[idxLevel] = new FComplexe***[this->size1Dim]; - - for(long idxD1 = 0 ; idxD1 < this->size1Dim; ++idxD1){ - //this->transferM2L[idxLevel][idxD1] = new FComplexe**[this->size1Dim]; - - for(long idxD2 = 0; idxD2 < this->size1Dim; ++idxD2){ - //this->transferM2L[idxLevel][idxD1][idxD2] = new FComplexe*[this->size1Dim]; - - for(long idxD3 = 0; idxD3 < this->size1Dim; ++idxD3){ - const int x = idxD1 - this->halphSize1Dim; - const int y = idxD2 - this->halphSize1Dim; - const int z = idxD3 - this->halphSize1Dim; - - if( ( x*x + y*y + z*z ) >= ( 3*this->FMB_Info_ws*this->FMB_Info_ws + 0.1 ) ){ - this->transferM2L[idxLevel][idxD1][idxD2][idxD3] = ff_block_matrix_Allocate_rec(0,0,FMB_Info_P); - } - else { - this->transferM2L[idxLevel][idxD1][idxD2][idxD3] = NULL; - } - } - } - } - } - } - - void ff_block_matrix_Free(block_matrix_t *p){ - if (p != NULL){ - /* Recursive calls: */ - ff_block_matrix_Free(p->below); - ff_block_matrix_Free(p->right); - - /* Free current block matrix: */ - delete(p->data); - - /* Free 'p' itself: */ - delete(p); - } - } - - // transfer_L2L_free - // transfer_M2M_free - // transfer_M2L_free - void transferDeallocate(){ - // M2M L2L - /*for(long idxLevel = 0 ; idxLevel < TreeHeight ; ++idxLevel){ - for(long idxChild = 0; idxChild < 8; ++idxChild){ - delete [] this->transitionM2M[idxLevel][idxChild]; - delete [] this->transitionL2L[idxLevel][idxChild]; - } - delete [] this->transitionM2M[idxLevel]; - delete [] transitionL2L[idxLevel]; - } - delete [] this->transitionM2M; - delete [] this->transitionL2L;*/ - // M2L - for(int idxLevel = 0 ; idxLevel < TreeHeight; ++idxLevel){ - for(long idxD1 = 0 ; idxD1 < this->size1Dim ; ++idxD1){ - for(long idxD2 = 0 ; idxD2 < this->size1Dim ; ++idxD2){ - for(long idxD3 = 0 ; idxD3 < this->size1Dim; ++idxD3){ - ff_block_matrix_Free(this->transferM2L[idxLevel][idxD1][idxD2][idxD3]); - } - //delete [] this->transferM2L[idxLevel][idxD1][idxD2]; - } - //delete [] this->transferM2L[idxLevel][idxD1]; - } - //delete [] this->transferM2L[idxLevel]; - } - //delete [] this->transferM2L; - } - - ////////////////////////////////////////////////////////////////// - // Utils - ////////////////////////////////////////////////////////////////// - - // position_2_r_cos_th_sin_th_ph - Spherical positionTsmphere(const F3DPosition& inVector){ - const FReal x2y2 = (inVector.getX() * inVector.getX()) + (inVector.getY() * inVector.getY()); - - Spherical outSphere; - - outSphere.r = FMath::Sqrt( x2y2 + (inVector.getZ() * inVector.getZ())); - outSphere.phi = FMath::Atan2(inVector.getY(),inVector.getX()); - outSphere.cosTheta = inVector.getZ() / outSphere.r; // cos_th = z/r - outSphere.sinTheta = FMath::Sqrt(x2y2) / outSphere.r; // sin_th = sqrt(x^2 + y^2)/r - - return outSphere; - } - - // associated_Legendre_function_Fill_complete_array_of_values_for_cos - void legendreFunction( const int lmax, const FReal inCosTheta, const FReal inSinTheta, FReal* const outResults ){ - // l=0: results[current++] = 1.0; // P_0^0(cosTheta) = 1 - int idxCurrent = 0; - outResults[idxCurrent++] = 1.0; - - // l=1: - // Compute P_1^{0} using (3) and store it into results_array: - outResults[idxCurrent++] = inCosTheta; - - // Compute P_1^1 using (2 bis) and store it into results_array - const FReal invSinTheta = -inSinTheta; // somx2 => -sinTheta - outResults[idxCurrent++] = invSinTheta; - - // l>1: - int idxCurrent1m = 1; //pointer on P_{l-1}^m P_1^0 - int idxCurrent2m = 0; //pointer on P_{l-2}^m P_0^0 - FReal fact = 3.0; - - // Remark: p_results_array_l_minus_1_m and p_results_array_l_minus_2_m - // just need to be incremented at each iteration. - for(int idxl = 2; idxl <= lmax ; ++idxl ){ - for( int idxm = 0; idxm <= idxl - 2 ; ++idxm , ++idxCurrent , ++idxCurrent1m , ++idxCurrent2m ){ - // Compute P_l^m, l >= m+2, using (1) and store it into results_array: - outResults[idxCurrent] = (inCosTheta * ( 2 * idxl - 1 ) * outResults[idxCurrent1m] - ( idxl + idxm - 1 ) - * outResults[idxCurrent2m] ) / ( idxl - idxm ); - printf("\tres (%.18e) = inCosTheta (%.18e) idxl (%d) outResults 1m (%.18e) idxm (%d) outResults 2m (%.18e)\n", - outResults[idxCurrent],inCosTheta,idxl,outResults[idxCurrent1m],idxm,outResults[idxCurrent2m]); - printf("\t\t temp1 = %.18e temp2 = %.18e temp3 = %.18e\n", - inCosTheta * ( 2 * idxl - 1 ) * outResults[idxCurrent1m], - ( idxl + idxm - 1 ) * outResults[idxCurrent2m], - (inCosTheta * ( 2 * idxl - 1 ) * outResults[idxCurrent1m] - ( idxl + idxm - 1 ) * outResults[idxCurrent2m] )); - } - // p_results_array_l_minus_1_m now points on P_{l-1}^{l-1} - - // Compute P_l^{l-1} using (3) and store it into ptrResults: - outResults[idxCurrent++] = inCosTheta * ( 2 * idxl - 1 ) * outResults[idxCurrent1m]; - - // Compute P_l^l using (2 bis) and store it into results_array: - outResults[idxCurrent++] = fact * invSinTheta * outResults[idxCurrent1m]; - - fact += 2.0; - ++idxCurrent1m; - } - - //for(int idxprint = 0 ; idxprint <= FMB_Info_M2L_P ; ++idxprint){ - // printf("\t legendre[%d] = %e\n",idxprint ,outResults[idxprint]); - //} - } - - // spherical_harmonic_Inner - //2.7 these - void harmonicInner(const Spherical& inSphere, FComplexe* const outResults){ - // p_precomputed_cos_and_sin_array - FComplexe cosSin[FMB_Info_M2L_P + 1]; - - for(int idxl = 0 , idxlMod4 = 0; idxl <= FMB_Info_P ; ++idxl, ++idxlMod4){ - if(idxlMod4 == 4) idxlMod4 = 0; - const FReal angleinter = FReal(idxl) * inSphere.phi; - const FReal angle = angleinter + this->PiArrayInner[idxlMod4]; - - cosSin[idxl].setReal( FMath::Sin(angle + FMath::FPiDiv2) ); - cosSin[idxl].setImag( FMath::Sin(angle) ); - - /*printf("%d=%.15e/%.15e (angle %.15e=%d * %.15e + %.15e // (%.15e))\n", - idxl,cosSin[idxl].getReal(),cosSin[idxl].getImag(), - angle,idxl,inSphere.phi,this->PiArrayInner[idxlMod4],angleinter);*/ - - /*printf("sin(%.15e) = %.15e\n", - angle + FMath::FPiDiv2,FMath::Sin(angle + FMath::FPiDiv2));*/ - } - - // p_associated_Legendre_function_Array - FReal legendre[FMB_Info_M2L_exp_size]; - legendreFunction(FMB_Info_P,inSphere.cosTheta, inSphere.sinTheta, legendre); - /*printf("FMB_Info_M2L_exp_size=%d\n",FMB_Info_M2L_exp_size); - for(int temp = 0 ; temp < FMB_Info_M2L_exp_size ; ++temp){ - printf("%e\n",legendre[temp]); - }*/ - - FComplexe* currentResult = outResults; - int idxLegendre = 0;//ptr_associated_Legendre_function_Array - int idxSphereHarmoCoef = 0; - FReal idxRl = 1.0 ; - - //printf("lmax = %d\n",FMB_Info_P); - for(int idxl = 0; idxl <= FMB_Info_P ; ++idxl, idxRl *= inSphere.r){ - for(int idxm = 0 ; idxm <= idxl ; ++idxm, ++currentResult, ++idxSphereHarmoCoef, ++idxLegendre){ - const FReal magnitude = this->sphereHarmoInnerCoef[idxSphereHarmoCoef] * idxRl * legendre[idxLegendre]; - currentResult->setReal( magnitude * cosSin[idxm].getReal() ); - currentResult->setImag( magnitude * cosSin[idxm].getImag() ); - - /*printf("\t\tl = %d m = %d\n",idxl,idxm); - printf("\t\tmagnitude (%e) = idxRl (%e) * sphereHarmoInnerCoef (%e) * legendre (%e)\n", - magnitude,idxRl,this->sphereHarmoInnerCoef[idxSphereHarmoCoef],legendre[idxLegendre]); - printf("\t\tresult real=%e imag=%e\n", - currentResult->getReal(),currentResult->getImag());*/ - } - } - - } - // spherical_harmonic_Outer - void harmonicOuter(const Spherical& inSphere, FComplexe* const outResults){ - // p_precomputed_cos_and_sin_array - FComplexe cosSin[FMB_Info_M2L_P + 1]; - - for(int idxl = 0, idxlMod4 = 0; idxl <= FMB_Info_M2L_P ; ++idxl, ++idxlMod4){ - if(idxlMod4 == 4) idxlMod4 = 0; - const FReal angle = idxl * inSphere.phi + this->PiArrayOuter[idxlMod4]; - - cosSin[idxl].setReal( FMath::Sin(angle + FMath::FPiDiv2) ); - cosSin[idxl].setImag( FMath::Sin(angle) ); - - //printf("l=%d \t inSphere.phi=%e \t this->PiArray[idxlMod4]=%e \t angle=%e \t FMath::Sin(angle + FMath::FPiDiv2)=%e \t FMath::Sin(angle)=%e\n", - // idxl, inSphere.phi, this->PiArrayOuter[idxlMod4], angle, FMath::Sin(angle + FMath::FPiDiv2) , FMath::Sin(angle)); - } - - // p_associated_Legendre_function_Array - FReal legendre[FMB_Info_M2L_exp_size]; - legendreFunction(FMB_Info_M2L_P,inSphere.cosTheta, inSphere.sinTheta, legendre); - - int idxLegendre = 0; - FComplexe* currentResult = outResults; - - const FReal invR = 1/inSphere.r; - FReal idxRl1 = invR; - for(int idxl = 0 ; idxl <= FMB_Info_M2L_P ; ++idxl, idxRl1 *= invR){ - for(int idxm = 0 ; idxm <= idxl ; ++idxm, ++currentResult, ++idxLegendre){ - const FReal magnitude = this->sphereHarmoOuterCoef[idxl-idxm] * idxRl1 * legendre[idxLegendre]; - currentResult->setReal( magnitude * cosSin[idxm].getReal() ); - currentResult->setImag( magnitude * cosSin[idxm].getImag() ); - //printf("l=%d\t m=%d\t idxRl1=%e\t magnitude=%e\n",idxl,idxm,idxRl1,magnitude); - //printf("l=%d\t m=%d\t cosSin[idxm].getReal()=%e\t cosSin[idxm].getImag()=%e\n", - // idxl,idxm,cosSin[idxm].getReal(),cosSin[idxm].getImag()); - //printf("this->sphereHarmoOuterCoef[idxl-idxm] = %e \t this->legendre[idxLegendre] = %e \n", - // this->sphereHarmoOuterCoef[idxl-idxm], - // this->legendre[idxLegendre]); - - //for(int idxTemp = 0 ; idxTemp <= idxl-idxm ; idxTemp++ ){ - // printf("\t this->sphereHarmoOuterCoef[%d] = %e\n", idxTemp,this->sphereHarmoOuterCoef[idxTemp] ); - //} - } - } - } - - /** spherical_harmonic_Inner_and_theta_derivated - * Returns the value of the partial derivative of the spherical harmonic - *relative to theta. We have for all m such that -(l-1) <= m <= l-1 : - * - *(d H_l^m(theta, phi))/(d theta) - *= (-1)^m sqrt((l-|m|)!/(l+|m|)!) (d P_l^{|m|}(cos theta))/(d theta) e^{i.m.phi} - *= (-1)^m sqrt((l-|m|)!/(l+|m|)!) 1/sqrt{1-cos^2 theta} [l cos theta P_l^{|m|}(cos theta) - (l+|m|) P_{l-1}^{|m|}(cos theta) ] e^{i.m.phi} - *Since theta is in the range [0, Pi], we have: sin theta > 0 and therefore - *sqrt{1-cos^2 theta} = sin theta. Thus: - * - *(d H_l^m(theta, phi))/(d theta) - *= (-1)^m sqrt((l-|m|)!/(l+|m|)!) 1/(sin theta) [l cos theta P_l^{|m|}(cos theta) - (l+|m|) P_{l-1}^{|m|}(cos theta) ] e^{i.m.phi} - *For |m|=l, we have~: - *(d H_l^l(theta, phi))/(d theta) - *= (-1)^m sqrt(1/(2l)!) 1/(sin theta) [l cos theta P_l^l(cos theta) ] e^{i.m.phi} - * - *Remark: for 0<m<=l: - *(d H_l^{-m}(theta, phi))/(d theta) = [(d H_l^{-m}(theta, phi))/(d theta)]* - * - * - * - *Therefore, we have for (d Inner_l^m(r, theta, phi))/(d theta): - * - *|m|<l: (d Inner_l^m(r, theta, phi))/(d theta) = - *(i^m (-1)^l / (l+|m|)!) 1/(sin theta) [l cos theta P_l^{|m|}(cos theta) - (l+|m|) P_{l-1}^{|m|}(cos theta) ] e^{i.m.phi} r^l - *|m|=l: (d Inner_l^m(r, theta, phi))/(d theta) = - *(i^m (-1)^l / (l+|m|)!) 1/(sin theta) [l cos theta P_l^l(cos theta) ] e^{i.m.phi} r^l - * - * - */ - void harmonicInnerThetaDerivated( - const Spherical& inSphere, - FComplexe * results_array, - FComplexe * theta_derivated_results_array - ){ - - //printf("HarmoInnerTheta \t lmax = %d \t r = %e \t cos_theta = %e \t sin_theta = %e \t phi = %e\n", - // FMB_Info_P,inSphere.r,inSphere.cosTheta,inSphere.sinTheta,inSphere.phi); - - // p_precomputed_cos_and_sin_array - FComplexe cosSin[FMB_Info_M2L_P + 1]; - - // Initialization of precomputed_cos_and_sin_array: - for(int idxm = 0 , idxmMod4 = 0; idxm <= FMB_Info_P ; ++idxm, ++idxmMod4){ - if(idxmMod4 == 4) idxmMod4 = 0; - const FReal angle = idxm*inSphere.phi + PiArrayInner[idxmMod4]; - cosSin[idxm].setReal(FMath::Sin(angle + FMath::FPiDiv2)); - cosSin[idxm].setImag(FMath::Sin(angle)); - - //printf("l=%d \t inSphere.phi=%e \t this->PiArrayOuter[idxlMod4]=%e \t angle=%e \t FMath::Sin(angle + FMath::FPiDiv2)=%e \t FMath::Sin(angle)=%e\n", - // idxm, inSphere.phi, this->PiArrayInner[idxmMod4], angle, FMath::Sin(angle + FMath::FPiDiv2) , FMath::Sin(angle)); - } - - // p_associated_Legendre_function_Array - FReal legendre[FMB_Info_M2L_exp_size]; - // Initialization of associated_Legendre_function_Array: - legendreFunction(FMB_Info_P, inSphere.cosTheta, inSphere.sinTheta, legendre); - - - FComplexe *p_term = results_array; - FComplexe *p_theta_derivated_term = theta_derivated_results_array; - FReal *p_spherical_harmonic_Inner_coefficients_array = sphereHarmoInnerCoef; - FReal *ptr_associated_Legendre_function_Array = legendre; - FReal *start_ptr_associated_Legendre_function_Array = ptr_associated_Legendre_function_Array; - - // r^l - FReal r_l = 1.0; - for (int l = 0 ; l <= FMB_Info_P ; ++l, r_l *= inSphere.r){ - FReal magnitude; - // m<l: - int m = 0; - for(; m < l ; ++m, ++p_term, ++p_theta_derivated_term, ++p_spherical_harmonic_Inner_coefficients_array, ++ptr_associated_Legendre_function_Array){ - magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * (*ptr_associated_Legendre_function_Array); - - // Computation of Inner_l^m(r, theta, phi): - p_term->setReal( magnitude * cosSin[m].getReal()); - p_term->setImag( magnitude * cosSin[m].getImag()); - - /*printf("%d/%d - magnitude=%e ptr_precomputed_cos_and_sin_array real=%e imag=%e p_term real=%e imag=%e\n", - l,m, - magnitude, - cosSin[m].getReal(), - cosSin[m].getImag(), - p_term->getReal(), - p_term->getImag());*/ - /*printf("\t p_spherical_harmonic_Inner_coefficients_array = %e \t ptr_associated_Legendre_function_Array = %e \t r_l = %e\n", - *p_spherical_harmonic_Inner_coefficients_array, - *ptr_associated_Legendre_function_Array, - r_l - );*/ - - // Computation of {\partial Inner_l^m(r, theta, phi)}/{\partial theta}: - magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * ((l*inSphere.cosTheta*(*ptr_associated_Legendre_function_Array) - - (l+m)*(*(start_ptr_associated_Legendre_function_Array + expansion_Redirection_array_for_j[l-1] + m))) / inSphere.sinTheta); - p_theta_derivated_term->setReal(magnitude * cosSin[m].getReal()); - p_theta_derivated_term->setImag(magnitude * cosSin[m].getImag()); - - //printf("magnitude=%e r_l=%e p_spherical_harmonic_Inner_coefficients_array=%e real=%e imag=%e\n", - // magnitude,r_l,*p_spherical_harmonic_Inner_coefficients_array,p_theta_derivated_term->getReal(),p_theta_derivated_term->getImag()); - } - - // m=l: - // Computation of Inner_m^m(r, theta, phi): - magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * (*ptr_associated_Legendre_function_Array); - p_term->setReal(magnitude * cosSin[m].getReal()); - p_term->setImag(magnitude * cosSin[m].getImag()); - - /*printf("%d - magnitude=%e ptr_precomputed_cos_and_sin_array real=%e imag=%e p_term real=%e imag=%e\n", - l, - magnitude, - cosSin[m].getReal(), - cosSin[m].getImag(), - p_term->getReal(), - p_term->getImag());*/ - /*printf("\t p_spherical_harmonic_Inner_coefficients_array = %e \t ptr_associated_Legendre_function_Array = %e \t r_l = %e\n", - *p_spherical_harmonic_Inner_coefficients_array, - *ptr_associated_Legendre_function_Array, - r_l - );*/ - - // Computation of {\partial Inner_m^m(r, theta, phi)}/{\partial theta}: - magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * (m * inSphere.cosTheta * (*ptr_associated_Legendre_function_Array) / inSphere.sinTheta); - p_theta_derivated_term->setReal(magnitude * cosSin[m].getReal()); - p_theta_derivated_term->setImag(magnitude * cosSin[m].getImag()); - - //printf("magnitude=%e r_l=%e p_spherical_harmonic_Inner_coefficients_array=%e real=%e imag=%e\n", - // magnitude,r_l,*p_spherical_harmonic_Inner_coefficients_array,p_theta_derivated_term->getReal(),p_theta_derivated_term->getImag()); - - ++p_term; - ++p_theta_derivated_term; - ++p_spherical_harmonic_Inner_coefficients_array; - ++ptr_associated_Legendre_function_Array; - } - } - - ////////////////////////////////////////////////////////////////// - // Precompute - ////////////////////////////////////////////////////////////////// - - // transfer_M2M_Precompute_all_levels - // transfer_L2L_Precompute_all_levels - void precomputeM2M(){ - FReal treeWidthAtLevel = this->treeWidthAtRoot/2; - - for(int idxLevel = 0 ; idxLevel < TreeHeight - 1 ; ++idxLevel ){ - const F3DPosition father(treeWidthAtLevel,treeWidthAtLevel,treeWidthAtLevel); - treeWidthAtLevel /= 2; - - //std::cout << "[precomputeM2M]treeWidthAtLevel=" << treeWidthAtLevel << "\n"; - //printf("\tidxLevel=%d\tFather.x=%e\tFather.y=%e\tFather.z=%e\n",idxLevel,father.getX(),father.getY(),father.getZ()); - - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild ){ - FTreeCoordinate childBox; - childBox.setPositionFromMorton(idxChild,1); - - const F3DPosition M2MVector ( - father.getX() - (treeWidthAtLevel * (1 + (childBox.getX() * 2))), - father.getY() - (treeWidthAtLevel * (1 + (childBox.getY() * 2))), - father.getZ() - (treeWidthAtLevel * (1 + (childBox.getZ() * 2))) - ); - - harmonicInner(positionTsmphere(M2MVector),this->transitionM2M[idxLevel][idxChild]); - - printf("[M2M_vector]%d/%d = %e/%e/%e\n", idxLevel , idxChild , M2MVector.getX() , M2MVector.getY() , M2MVector.getZ() ); - Spherical sphericalM2M = positionTsmphere(M2MVector); - printf("[M2M_vectorSpherical]%d/%d = %e/%e/%e/%e\n", - idxLevel , idxChild , sphericalM2M.r , sphericalM2M.cosTheta , sphericalM2M.sinTheta , sphericalM2M.phi ); - for(int idxExpSize = 0 ; idxExpSize < FMB_Info_exp_size ; ++idxExpSize){ - printf("transitionM2M[%d][%d][%d]=%e/%e\n", idxLevel , idxChild , idxExpSize , this->transitionM2M[idxLevel][idxChild][idxExpSize].getReal(),this->transitionM2M[idxLevel][idxChild][idxExpSize].getImag()); - } - exit(0);//todo remove - - const F3DPosition L2LVector ( - (treeWidthAtLevel * (1 + (childBox.getX() * 2))) - father.getX(), - (treeWidthAtLevel * (1 + (childBox.getY() * 2))) - father.getY(), - (treeWidthAtLevel * (1 + (childBox.getZ() * 2))) - father.getZ() - ); - - harmonicInner(positionTsmphere(L2LVector),this->transitionL2L[idxLevel][idxChild]); - - } - } - } - - void ff_block_matrix_Fill_data(FComplexe* transfer_exp, - FComplexe* data, - int M, - int N, - int nb_block_rows /* number of rows (counted by block) */, - int nb_block_columns /* number of colums (counted by block) */){ - int NN, MM; - int n, m; - int k; - int P = FMB_Info_P; - - /* matrix stored by rows */ - int NN_stop; - - for (MM=M; MM <= M + nb_block_rows - 1 ; ++MM){ - for (m=0; - m<=MM; /* Only positive orders for local expansion: */ - ++m){ - - NN_stop = FMath::Min(N + nb_block_columns - 1, P-MM); - - for (NN=N; NN <= NN_stop; ++NN){ - for (n=0; - n<=2*NN; - ++n, - ++data){ - - /* Not optimized: */ - k = NN-n-m; - if (k < 0){ - const int pow_of_minus_1 = ((k%2) ? -1 : 1); - data->setReal( pow_of_minus_1 * (transfer_exp + expansion_Redirection_array_for_j[MM+NN] - k)->getReal()); - data->setImag((-pow_of_minus_1) * (transfer_exp + expansion_Redirection_array_for_j[MM+NN] - k)->getImag()); - } - else { - *data = *(transfer_exp + expansion_Redirection_array_for_j[MM+NN] + k); - } - - //printf("MM %d m %d NN %d ; data %e %e\n", - // MM,m,NN,data->getReal(),data->getImag()); - } /* for m */ - } /* for MM */ - - } /* for n */ - } /* for NN */ - - } - - void ff_matrix_Convert_exp_2_ff_block_matrix(FComplexe* const transfer_exp, - block_matrix_t *p_transfer_block_matrix){ - int P = p_transfer_block_matrix->P_block; - int M = p_transfer_block_matrix->M_block; - int N = p_transfer_block_matrix->N_block; - - - /* "p_transfer_block_matrix->below == NULL" implies - * "p_transfer_block_matrix->right == NULL" too. - * - * We can also test: " if (ff_block_matrix_Is_terminal_case(M, N, P, FMB_Info.stop_for_block)) " - */ - if (p_transfer_block_matrix->below == NULL) { - /*************** Treat terminal case: ***************/ - /* The 'P+1' bands are stored one after the other, starting from p_transfer_block_matrix->data, - * so that the leading dimension is the smallest one. */ - int row_nb ; - int column_nb ; - int band_number; - int P_bn_1; /* will contain ' P - band_number +1 ' */ - - FComplexe* data = p_transfer_block_matrix->data; - - P_bn_1 = P+1; - for (band_number=0; band_number<=P; ++band_number){ - row_nb = M + band_number + 1; - column_nb = (P_bn_1) * (P_bn_1 + 2*N); - - ff_block_matrix_Fill_data(transfer_exp, data, M + band_number, N, 1, P_bn_1); - data += row_nb * column_nb; /* set data to start of next band */ - --P_bn_1; - } - } - else { - /*************** Recursive case: ***************/ - int q = P/2; - - /* Fill the biggest square sub-matrix ('square' in the number of - * blocks, in each dimension, it contains). */ - /* bssm: biggest square sub-matrix */ - ff_block_matrix_Fill_data(transfer_exp, p_transfer_block_matrix->data, M, N, q+1, q+1); - - - /* Recursive calls: */ - /* Sub-matrix "below": */ - ff_matrix_Convert_exp_2_ff_block_matrix(transfer_exp, p_transfer_block_matrix->below); - - /* Sub-matrix "on the right": */ - ff_matrix_Convert_exp_2_ff_block_matrix(transfer_exp, p_transfer_block_matrix->right); - - } - } - - - // transfer_M2L_Precompute_all_levels - void precomputeM2L(){ - //[Blas] FComplexe tempComplexe[FMB_Info_M2L_exp_size]; - //printf("FMB_Info.M2L_exp_size = %d\n",FMB_Info_M2L_exp_size); - - FReal treeWidthAtLevel = this->treeWidthAtRoot; - for(int idxLevel = 0 ; idxLevel < TreeHeight ; ++idxLevel ){ - //printf("level = %d \t width = %lf\n",idxLevel,treeWidthAtLevel); - for( int idxd1 = 0; idxd1 < this->size1Dim ; ++idxd1 ){ - - for( int idxd2 = 0; idxd2 < this->size1Dim ; ++idxd2 ){ - - for( int idxd3 = 0; idxd3 < this->size1Dim ; ++idxd3 ){ - const long x = idxd1 - this->halphSize1Dim; - const long y = idxd2 - this->halphSize1Dim; - const long z = idxd3 - this->halphSize1Dim; - - //printf("x=%ld \t y=%ld \t z=%ld\n",x,y,z); - - if( ( x*x + y*y + z*z ) >= ( 3*FMB_Info_ws*FMB_Info_ws + 0.1 ) ){ - const F3DPosition relativePos( x*treeWidthAtLevel , y*treeWidthAtLevel , z*treeWidthAtLevel ); - - - //printf("blas\n"); - //printf("transferM2L[%d][%d][%d][%d]\n", idxLevel, idxd1, idxd2, idxd3); - FComplexe tempComplexe[FMB_Info_M2L_exp_size]; - harmonicOuter(positionTsmphere(relativePos),tempComplexe); - - //ff_matrix_Convert_exp_2_transfer_M2L_matrix - ff_matrix_Convert_exp_2_ff_block_matrix(tempComplexe,this->transferM2L[idxLevel][idxd1][idxd2][idxd3]); - - /*for(int idxTemp = 0 ; idxTemp < FMB_Info_M2L_exp_size ; ++idxTemp){ - printf("transferM2L[%d][%d][%d][%d][%d]=%e/%e\n", - idxLevel,idxd1,idxd2,idxd3,idxTemp, - tempComplexe[idxTemp].getReal(), - tempComplexe[idxTemp].getImag()); - }*/ - } - - } - } - } - treeWidthAtLevel /= 2; - } - } - - void buildPrecompute(){ - expansion_Redirection_array_for_j_Initialize(); - sphericalHarmonicInitialize(); - transferAllocate(); - - precomputeM2M(); - precomputeM2L(); - } - -public: - FFmbKernelsBlockBlas(const FReal inTreeWidth) : - treeWidthAtRoot(inTreeWidth) { - buildPrecompute(); - } - - FFmbKernelsBlockBlas(const FFmbKernelsBlockBlas& other) - : treeWidthAtRoot(other.treeWidthAtRoot) { - buildPrecompute(); - } - - virtual void init(){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - /** Default destructor */ - virtual ~FFmbKernelsBlockBlas(){ - transferDeallocate(); - } - - - ///////////////////////////////////////////////////////////////////////////////// - // Upward - ///////////////////////////////////////////////////////////////////////////////// - - /** OK! - * expansion_P2M_add - * Multipole expansion with m charges q_i in Q_i=(rho_i, alpha_i, beta_i) - *whose relative coordinates according to *p_center are: - *Q_i - *p_center = (rho'_i, alpha'_i, beta'_i); - * - *For j=0..P, k=-j..j, we have: - * - *M_j^k = (-1)^j { sum{i=1..m} q_i Inner_j^k(rho'_i, alpha'_i, beta'_i) } - * - *However the extern loop is over the bodies (i=1..m) in our code and as an - *intern loop we have: j=0..P, k=-j..j - * - *and the potential is then given by: - * - * Phi(x) = sum_{n=0}^{+} sum_{m=-n}^{n} M_n^m O_n^{-m} (x - *p_center) - * - */ - void P2M(CellClass* const inPole, const FList<ParticleClass*>* const inParticles) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - - for(typename FList<ParticleClass*>::ConstBasicIterator iterParticle(*inParticles); - iterParticle.isValide() ; iterParticle.progress()){ - - - //std::cout << "Working on part " << iterParticle.value()->getPhysicalValue() << "\n"; - //F3DPosition tempPos = iterParticle.value()->getPosition() - inPole->getPosition(); - //ok printf("\tpos_rel.x=%e\tpos_rel.y=%e\tpos_rel.z=%e\n",tempPos.getX(),tempPos.getY(),tempPos.getZ()); - //ok printf("\tp_center.x=%e\tp_center.y=%e\tp_center.z=%e\n",inPole->getPosition().getX(),inPole->getPosition().getY(),inPole->getPosition().getZ()); - //ok printf("\tbody.x=%e\tbody.y=%e\tbody.z=%e\n",iterParticle.value()->getPosition().getX(),iterParticle.value()->getPosition().getY(),iterParticle.value()->getPosition().getZ()); - - harmonicInner(positionTsmphere(iterParticle.value()->getPosition() - inPole->getPosition()),current_thread_Y); - - //ok printf("\tr=%e\tcos_theta=%e\tsin_theta=%e\tphi=%e\n",spherical.r,spherical.cosTheta,spherical.sinTheta,spherical.phi); - - FComplexe* p_exp_term = inPole->getMultipole(); - FComplexe* p_Y_term = current_thread_Y; - FReal pow_of_minus_1_j = 1.0;//(-1)^j - const FReal valueParticle = iterParticle.value()->getPhysicalValue(); - - for(int j = 0 ; j <= FMB_Info_P ; ++j, pow_of_minus_1_j = -pow_of_minus_1_j ){ - for(int k = 0 ; k <= j ; ++k, ++p_Y_term, ++p_exp_term){ - p_Y_term->mulRealAndImag( valueParticle * pow_of_minus_1_j ); - (*p_exp_term) += (*p_Y_term); - //printf("\tj=%d\tk=%d\tp_exp_term.real=%e\tp_exp_term.imag=%e\tp_Y_term.real=%e\tp_Y_term.imag=%e\tpow_of_minus_1_j=%e\n", - // j,k,(*p_exp_term).getReal(),(*p_exp_term).getImag(),(*p_Y_term).getReal(),(*p_Y_term).getImag(),pow_of_minus_1_j); - } - } - } - - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - /** - *----------------------------------- - *octree_Upward_pass_internal_cell - *expansion_M2M_add - *----------------------------------- - *We compute the translation of multipole_exp_src from *p_center_of_exp_src to - *p_center_of_exp_target, and add the result to multipole_exp_target. - * - * O_n^l (with n=0..P, l=-n..n) being the former multipole expansion terms - * (whose center is *p_center_of_multipole_exp_src) we have for the new multipole - * expansion terms (whose center is *p_center_of_multipole_exp_target): - - * M_j^k = sum{n=0..j} - * sum{l=-n..n, |k-l|<=j-n} - * O_n^l Inner_{j-n}^{k-l}(rho, alpha, beta) - * - * where (rho, alpha, beta) are the spherical coordinates of the vector : - * p_center_of_multipole_exp_target - *p_center_of_multipole_exp_src - * - * Warning: if j-n < |k-l| we do nothing. - */ - void M2M(CellClass* const FRestrict inPole, const CellClass *const FRestrict *const FRestrict inChild, const int inLevel) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - - // We do NOT have: for(l=n-j+k; l<=j-n+k ;++l){} <=> for(l=-n; l<=n ;++l){if (j-n >= abs(k-l)){}} - // But we have: for(k=MAX(0,n-j+l); k<=j-n+l; ++k){} <=> for(k=0; k<=j; ++k){if (j-n >= abs(k-l)){}} - // (This is not the same as in L2L since the range of values of k is not the same, compared to "n-j" or "j-n".) - // Therefore the loops over n and l are the outmost ones and - // we invert the loop over j with the summation with n: - // for{j=0..P} sum_{n=0}^j <-> sum_{n=0}^P for{j=n..P} - FComplexe* const multipole_exp_target = inPole->getMultipole(); - //printf("Morton = %lld\n",inPole->getMortonIndex()); - - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - if(!inChild[idxChild]) continue; - //printf("\tChild %d\n",idxChild); - - const FComplexe* const multipole_exp_src = inChild[idxChild]->getMultipole(); - - const FComplexe* const M2M_transfer = transitionM2M[inLevel][idxChild]; - - for(int n = 0 ; n <= FMB_Info_P ; ++n ){ - // l<0 // (-1)^l - FReal pow_of_minus_1_for_l = ( n % 2 ? -1 : 1); - - // O_n^l : here points on the source multipole expansion term of degree n and order |l| - const FComplexe* p_src_exp_term = multipole_exp_src + expansion_Redirection_array_for_j[n]+n; - //printf("\t[p_src_exp_term] expansion_Redirection_array_for_j[n]=%d\tn=%d\n",expansion_Redirection_array_for_j[n],n); - - int l = -n; - for(; l<0 ; ++l, --p_src_exp_term, pow_of_minus_1_for_l = -pow_of_minus_1_for_l){ - - for(int j = n ; j<= FMB_Info_P ; ++j ){ - // M_j^k - FComplexe *p_target_exp_term = multipole_exp_target + expansion_Redirection_array_for_j[j]; - //printf("\t[p_target_exp_term] expansion_Redirection_array_for_j[j]=%d\n",expansion_Redirection_array_for_j[j]); - // Inner_{j-n}^{k-l} : here points on the M2M transfer function/expansion term of degree n-j and order |k-l| - const FComplexe *p_Inner_term= M2M_transfer + expansion_Redirection_array_for_j[j-n]-l /* k==0 */; - //printf("\t[p_Inner_term] expansion_Redirection_array_for_j[j-n]=%d\tl=%d\n",expansion_Redirection_array_for_j[j-n],-l); - - // since n-j+l<0 - for(int k=0 ; k <= (j-n+l) ; ++k, ++p_target_exp_term, ++p_Inner_term){ // l<0 && k>=0 => k-l>0 - p_target_exp_term->incReal( pow_of_minus_1_for_l * - ((p_src_exp_term->getReal() * p_Inner_term->getReal()) + - (p_src_exp_term->getImag() * p_Inner_term->getImag()))); - p_target_exp_term->incImag( pow_of_minus_1_for_l * - ((p_src_exp_term->getReal() * p_Inner_term->getImag()) - - (p_src_exp_term->getImag() * p_Inner_term->getReal()))); - /*printf("1\n"); - printf("\tp_src_exp_term->dat[REAL]=%e\tp_src_exp_term->dat[IMAG]=%e\n", p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\tp_Inner_term->dat[REAL]=%e\tp_Inner_term->dat[IMAG]=%e\n", p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\tn[%d]l[%d]j[%d]k[%d] = %e / %e\n", - n,l,j,k, - p_target_exp_term->getReal(),p_target_exp_term->getImag());*/ - } // for k - } // for j - } // for l - - // l>=0 - for(; l <= n ; ++l, ++p_src_exp_term, pow_of_minus_1_for_l = -pow_of_minus_1_for_l){ - - for( int j=n ; j <= FMB_Info_P ; ++j ){ - // (-1)^k - FReal pow_of_minus_1_for_k = ( FMath::Max(0,n-j+l) %2 ? -1 : 1 ); - // M_j^k - FComplexe *p_target_exp_term = multipole_exp_target + expansion_Redirection_array_for_j[j] + FMath::Max(0,n-j+l); - // Inner_{j-n}^{k-l} : here points on the M2M transfer function/expansion term of degree n-j and order |k-l| - const FComplexe *p_Inner_term = M2M_transfer + expansion_Redirection_array_for_j[j-n] + l - FMath::Max(0,n-j+l);// -(k-l) - - int k = FMath::Max(0,n-j+l); - for(; k <= (j-n+l) && (k-l) < 0 ; ++k, ++p_target_exp_term, --p_Inner_term, pow_of_minus_1_for_k = -pow_of_minus_1_for_k){ /* l>=0 && k-l<0 */ - p_target_exp_term->incReal( pow_of_minus_1_for_k * pow_of_minus_1_for_l * - ((p_src_exp_term->getReal() * p_Inner_term->getReal()) + - (p_src_exp_term->getImag() * p_Inner_term->getImag()))); - p_target_exp_term->incImag(pow_of_minus_1_for_k * pow_of_minus_1_for_l * - ((p_src_exp_term->getImag() * p_Inner_term->getReal()) - - (p_src_exp_term->getReal() * p_Inner_term->getImag()))); - /*printf("2\n"); - printf("\tp_src_exp_term->dat[REAL]=%e\tp_src_exp_term->dat[IMAG]=%e\n", p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\tp_Inner_term->dat[REAL]=%e\tp_Inner_term->dat[IMAG]=%e\n", p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\tn[%d]l[%d]j[%d]k[%d] = %e / %e\n", - n,l,j,k, - p_target_exp_term->getReal(),p_target_exp_term->getImag());*/ - } // for k - - for(; k <= (j - n + l) ; ++k, ++p_target_exp_term, ++p_Inner_term){ // l>=0 && k-l>=0 - p_target_exp_term->incReal( - (p_src_exp_term->getReal() * p_Inner_term->getReal()) - - (p_src_exp_term->getImag() * p_Inner_term->getImag())); - p_target_exp_term->incImag( - (p_src_exp_term->getImag() * p_Inner_term->getReal()) + - (p_src_exp_term->getReal() * p_Inner_term->getImag())); - /*printf("3\n"); - printf("\tp_src_exp_term->dat[REAL]=%e\tp_src_exp_term->dat[IMAG]=%e\n", p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\tp_Inner_term->dat[REAL]=%e\tp_Inner_term->dat[IMAG]=%e\n", p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\tn[%d]l[%d]j[%d]k[%d] = %e / %e\n", - n,l,j,k, - p_target_exp_term->getReal(),p_target_exp_term->getImag());*/ - - } // for k - } // for j - } // for l - } // for n - } - - /*for(int idxPole = 0 ; idxPole < FMB_Info_M2L_exp_size ; ++idxPole){ - printf("[%d] real %e imag %e\n", - idxPole, - multipole_exp_target[idxPole].getReal(), - multipole_exp_target[idxPole].getImag()); - }*/ - - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - void convert_exp2nexp_inplace(FComplexe* const exp){ - int j, k; - const int P = FMB_Info_P; - FReal pow_of_minus_1_for_k; - FComplexe* p_exp = NULL; - FComplexe* p_nexp = NULL; - - for (j=P; j>=0; --j){ - /* Position in 'exp': (j*(j+1)*0.5) + k - * Position in 'nexp': j*(j+1) + k - */ - int jj_plus_1 = j*(j+1); - int half_jj_plus_1 = (int) jj_plus_1*0.5; - p_exp = exp + half_jj_plus_1 + j; - p_nexp = exp + jj_plus_1 + j; - - /* Positive (or null) orders: */ - for (k=j; k>=0; --k){ - *p_nexp = *p_exp; - //printf("[%d] real = %e imag %e\n",p_nexp-exp,p_nexp->getReal(),p_nexp->getImag()); - --p_exp; - --p_nexp; - } /* for k */ - - /* Negative orders: */ - p_exp += j+1 + half_jj_plus_1; - p_nexp -= j-1; - for (k= -j, - pow_of_minus_1_for_k = ((j%2) ? -1 : 1); - k<0; - ++k, - pow_of_minus_1_for_k = -pow_of_minus_1_for_k){ - p_nexp->setReal(pow_of_minus_1_for_k * p_exp->getReal()); - p_nexp->setImag((-pow_of_minus_1_for_k) * p_exp->getImag()); - //printf("[%d] real = %e imag %e\n",p_nexp-exp,p_nexp->getReal(),p_nexp->getImag()); - --p_exp; - ++p_nexp; - } /* for k */ - - } /* j */ - } - - ///////////////////////////////////////////////////////////////////////////////// - // M2L - ///////////////////////////////////////////////////////////////////////////////// - - void ff_block_matrix_Product(FComplexe* local_exp, - const FComplexe* multipole_nexp, - block_matrix_t* p_transfer_block_matrix){ - - int P = p_transfer_block_matrix->P_block; - int M = p_transfer_block_matrix->M_block; - int N = p_transfer_block_matrix->N_block; - - FComplexe exp_term_tmp; - - FReal alpha_and_beta[2] = {1.0,0.0}; - - /* fprintf(stdout, "ff_block_matrix_Product() with P=%i, M=%i, N=%i\n", P, M, N); */ - - /* "p_transfer_block_matrix->below == NULL" implies - * "p_transfer_block_matrix->right == NULL" too. - * - * We can also test: " if (ff_block_matrix_Is_terminal_case(M, N, P, FMB_Info.stop_for_block)) " - */ - if (p_transfer_block_matrix->below == NULL) { - /*************** Treat terminal case: ***************/ - int row_nb ; - int column_nb ; - int band_number; - FComplexe *data = p_transfer_block_matrix->data; - int P_bn_1; /* will contain ' P - band_number +1 ' */ - - /* We do a product with "bands": there is P+1 bands: */ - - /* HPMSTART_DETAILED(60, "M2L blas BLOCK: terminale case"); */ - - /* First band (band_number == 0): a level 1 BLAS can be faster: */ - row_nb = M+1; - column_nb = (P+1)*(P+1 + 2*N); /* see below */ - - if (row_nb == 1){ /* level 1 BLAS is faster */ - - cblas_dotu_sub<FReal>(column_nb, - data, 1, - multipole_nexp, 1, - &exp_term_tmp); - local_exp->incReal(exp_term_tmp.getReal()); - local_exp->incImag(exp_term_tmp.getImag()); - } - else { - cblas_gemv<FReal>(CblasColMajor, CblasTrans, - column_nb, row_nb, - alpha_and_beta, data, column_nb, - multipole_nexp, 1, - alpha_and_beta, local_exp, 1); - } - - data += row_nb * column_nb; /* set data to start of next band: see below */ - local_exp += row_nb; /* update 'local_exp' */ - - - /* Other bands: - * the bands are stored one after the other, starting from p_ff_transfer_matrix->data, - * so that the leading dimension is the smallest one */ - P_bn_1 = P; - for (band_number=1; - band_number<=P; - ++band_number){ - row_nb = M + band_number + 1; - column_nb = (P_bn_1) * (P_bn_1 + 2*N); /* sum_{k=0}^{P-band_number} (2*(N+k) +1) - * = sum_{k=0}^{P-band_number} (2*k+1) + 2*N*(P-band_number+1) - * = (P-band_number+1)(P-band_number+1 + 2*N) */ - cblas_gemv<FReal>(CblasColMajor, CblasTrans, - column_nb, row_nb, - alpha_and_beta, data, column_nb, - multipole_nexp, 1, - alpha_and_beta, local_exp, 1); - - data += row_nb * column_nb; /* set data to start of next band */ - local_exp += row_nb; /* update 'local_exp' */ - --P_bn_1; - } - - /* HPMSTOP_DETAILED(60); */ - } - else { - /*************** Recursive case: ***************/ - /* Matrix-vector product with the biggest square sub-matrix - * ('square' in the number of - * blocks, in each dimension, it contains). */ - /* bssm: biggest square sub-matrix */ - int bssm_row_dim = p_transfer_block_matrix->bssm_row_dim; - int bssm_column_dim = p_transfer_block_matrix->bssm_column_dim; - - /* HPMSTART_DETAILED(61, "M2L blas BLOCK: bssm"); */ - - cblas_gemv<FReal>(CblasColMajor, CblasTrans, - bssm_column_dim, bssm_row_dim, - alpha_and_beta, p_transfer_block_matrix->data, bssm_column_dim, - multipole_nexp, 1, - alpha_and_beta, local_exp, 1); - - /* HPMSTOP_DETAILED(61); */ - - /* Recursive calls: */ - /* IMPORTANT: we perform all the products with the - * sub-matrices on the right before performing calls for - * sub-matrices below, since we will hence browse only once - * the "local exp vector" (for writing) and browse several - * times the "multipole exp vector" (but only for reading). */ - /* Sub-matrix "on the right": */ - ff_block_matrix_Product(local_exp, - multipole_nexp + bssm_column_dim, - p_transfer_block_matrix->right); - - /* Sub-matrix "below": */ - ff_block_matrix_Product(local_exp + bssm_row_dim, - multipole_nexp, - p_transfer_block_matrix->below); - - - } - } - - /** - *------------------ - * ff_block_matrix_Product - * ff_matrix_Product - * octree_Compute_local_exp_M2L - *------------------- - *We compute the conversion of multipole_exp_src in *p_center_of_exp_src to - *a local expansion in *p_center_of_exp_target, and add the result to local_exp_target. - * - *O_n^l (with n=0..P, l=-n..n) being the former multipole expansion terms - *(whose center is *p_center_of_multipole_exp_src) we have for the new local - *expansion terms (whose center is *p_center_of_local_exp_target): - * - *L_j^k = sum{n=0..+} - *sum{l=-n..n} - *O_n^l Outer_{j+n}^{-k-l}(rho, alpha, beta) - * - *where (rho, alpha, beta) are the spherical coordinates of the vector : - *p_center_of_local_exp_src - *p_center_of_multipole_exp_target - * - *Remark: here we have always j+n >= |-k-l| - * - */ - void M2L(CellClass* const FRestrict pole, const CellClass*const FRestrict *const FRestrict distantNeighbors, const int size, const int inLevel) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - FTreeCoordinate coordCenter; - coordCenter.setPositionFromMorton(pole->getMortonIndex(),inLevel); - - for(int idxSize = 0 ; idxSize < size ; ++idxSize){ - FTreeCoordinate coordNeighbors; - coordNeighbors.setPositionFromMorton(distantNeighbors[idxSize]->getMortonIndex(),inLevel); - - //printf("Morton = %lld\n",pole->getMortonIndex()); - //printf("\tMorton Neighbors = %lld\n",distantNeighbors[idxSize]->getMortonIndex()); - //printf("\tidxSize = %d\tleve = %d\tMorton = %lld\n",idxSize,inLevel,distantNeighbors[idxSize]->getMortonIndex()); - - block_matrix_t* const transfer_M2L_matrix = transferM2L[inLevel] - [(coordCenter.getX()+halphSize1Dim-coordNeighbors.getX())] - [(coordCenter.getY()+halphSize1Dim-coordNeighbors.getY())] - [(coordCenter.getZ()+halphSize1Dim-coordNeighbors.getZ())]; - //printf("level = %d\tx=%ld\ty=%ld\tz=%ld\n", inLevel, - // (coordCenter.getX()-coordNeighbors.getX()), - // (coordCenter.getY()-coordNeighbors.getY()), - // (coordCenter.getZ()-coordNeighbors.getZ())); - /*printf("M2L_transfer[0]= %e/%e\n",M2L_transfer->getReal(),M2L_transfer->getImag()); - printf("M2L_transfer[1]= %e/%e\n",M2L_transfer[1].getReal(),M2L_transfer[1].getImag()); - printf("M2L_transfer[2]= %e/%e\n",M2L_transfer[2].getReal(),M2L_transfer[2].getImag());*/ - const FComplexe* const multipole_exp_src = distantNeighbors[idxSize]->getMultipole(); - FComplexe* p_target_exp_term = pole->getLocal(); - - FComplexe multipole_exp_src_changed[FF_MATRIX_COLUMN_DIM]; - memcpy(multipole_exp_src_changed,multipole_exp_src,sizeof(FComplexe)*FF_MATRIX_ROW_DIM); - - convert_exp2nexp_inplace(multipole_exp_src_changed); - - ff_block_matrix_Product(p_target_exp_term,multipole_exp_src_changed,transfer_M2L_matrix); - - /*for(int j = 0 ; j < FF_MATRIX_COLUMN_DIM ; ++j){ - printf("\t\t multipole_nexp[%d] real = %e imag = %e\n", - j, - ((double*)multipole_exp_src_changed)[2*j], - ((double*)multipole_exp_src_changed)[2*j + 1]); - }*/ - } - - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - ///////////////////////////////////////////////////////////////////////////////// - // Downard - ///////////////////////////////////////////////////////////////////////////////// - - /** expansion_L2L_add - *We compute the shift of local_exp_src from *p_center_of_exp_src to - *p_center_of_exp_target, and set the result to local_exp_target. - * - *O_n^l (with n=0..P, l=-n..n) being the former local expansion terms - *(whose center is *p_center_of_exp_src) we have for the new local - *expansion terms (whose center is *p_center_of_exp_target): - * - *L_j^k = sum{n=j..P} - *sum{l=-n..n} - *O_n^l Inner_{n-j}^{l-k}(rho, alpha, beta) - * - *where (rho, alpha, beta) are the spherical coordinates of the vector : - *p_center_of_exp_target - *p_center_of_exp_src - * - *Warning: if |l-k| > n-j, we do nothing. - */ - void L2L(const CellClass* const FRestrict pole, CellClass* FRestrict *const FRestrict child, const int inLevel) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - // if no child at this position - if(!child[idxChild]) continue; - - const FComplexe* const L2L_tranfer = transitionL2L[inLevel][idxChild]; - const FComplexe* const local_exp_src = pole->getLocal(); - FComplexe* const local_exp_target = child[idxChild]->getLocal(); - - //printf("Level %d\n", inLevel); - //printf("Father morton %lld\n", pole->getMortonIndex()); - //printf("Child morton %lld\n", child[idxChild]->getMortonIndex()); - - //printf("local exp target %h\n", local_exp_target); - - // L_j^k - FComplexe* p_target_exp_term = local_exp_target; - for (int j=0 ; j<= FMB_Info_P ; ++j){ - // (-1)^k - FReal pow_of_minus_1_for_k = 1.0; - for (int k=0 ; k <= j ; ++k, pow_of_minus_1_for_k = -pow_of_minus_1_for_k, ++p_target_exp_term){ - for (int n=j; n<=FMB_Info_P;++n){ - // O_n^l : here points on the source multipole expansion term of degree n and order |l| - const FComplexe* p_src_exp_term = local_exp_src + expansion_Redirection_array_for_j[n] + n-j+k; - //printf("expansion_Redirection_array_for_j[n] + n-j+k %d\n", expansion_Redirection_array_for_j[n] + n-j+k); - int l = n-j+k; - // Inner_{n-j}^{l-k} : here points on the L2L transfer function/expansion term of degree n-j and order |l-k| - const FComplexe* p_Inner_term = L2L_tranfer + expansion_Redirection_array_for_j[n-j] + l-k; - - //printf("1\n"); - for ( ; l-k>0; --l, --p_src_exp_term, --p_Inner_term){ /* l>0 && l-k>0 */ - p_target_exp_term->incReal( (p_src_exp_term->getReal() * p_Inner_term->getReal()) - - (p_src_exp_term->getImag() * p_Inner_term->getImag())); - p_target_exp_term->incImag( (p_src_exp_term->getImag() * p_Inner_term->getReal()) + - (p_src_exp_term->getReal() * p_Inner_term->getImag())); - /*printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n", - p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\t p_Inner_term->real = %lf \t p_Inner_term->imag = %lf \n", - p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - p_target_exp_term->getReal(),p_target_exp_term->getImag()); - printf("\tp_target_exp_term = %d\n",p_target_exp_term-local_exp_target);*/ - } - - //printf("2\n"); - // (-1)^l - FReal pow_of_minus_1_for_l = ((l%2) ? -1 : 1); - for (; l>0 && l>=j-n+k; --l, pow_of_minus_1_for_l = -pow_of_minus_1_for_l, --p_src_exp_term, ++p_Inner_term){ /* l>0 && l-k<=0 */ - p_target_exp_term->incReal( pow_of_minus_1_for_l * pow_of_minus_1_for_k * - ((p_src_exp_term->getReal() * p_Inner_term->getReal()) + - (p_src_exp_term->getImag() * p_Inner_term->getImag()))); - p_target_exp_term->incImag( pow_of_minus_1_for_l * pow_of_minus_1_for_k * - ((p_src_exp_term->getImag() * p_Inner_term->getReal()) - - (p_src_exp_term->getReal() * p_Inner_term->getImag()))); - /*printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n", - p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\t p_Inner_term->real = %lf \t p_Inner_term->imag = %lf \n", - p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - p_target_exp_term->getReal(),p_target_exp_term->getImag()); - printf("\tp_target_exp_term = %d\n",p_target_exp_term-local_exp_target);*/ - } - - //printf("3\n"); - // l<=0 && l-k<=0 - for (; l>=j-n+k; --l, ++p_src_exp_term, ++p_Inner_term){ - p_target_exp_term->incReal( pow_of_minus_1_for_k * - ((p_src_exp_term->getReal() * p_Inner_term->getReal()) - - (p_src_exp_term->getImag() * p_Inner_term->getImag()))); - p_target_exp_term->decImag( pow_of_minus_1_for_k * - ((p_src_exp_term->getImag() * p_Inner_term->getReal()) + - (p_src_exp_term->getReal() * p_Inner_term->getImag()))); - /*printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n", - p_src_exp_term->getReal(),p_src_exp_term->getImag()); - printf("\t p_Inner_term->real = %lf \t p_Inner_term->imag = %lf \n", - p_Inner_term->getReal(),p_Inner_term->getImag()); - printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - p_target_exp_term->getReal(),p_target_exp_term->getImag()); - printf("\tj=%d\tk=%d\tn=%d\tl=%d\tpow_of_minus_1_for_k=%e\n",j,k,n,l,pow_of_minus_1_for_k); - printf("\tp_target_exp_term = %d\n",p_target_exp_term-local_exp_target);*/ - } - /*printf("\tj=%d\tk=%d\tn=%d\tl=%d\n",j,k,n,l); - printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n", - p_target_exp_term->getReal(),p_target_exp_term->getImag());*/ - } - } - } - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - - /** bodies_L2P - * expansion_L2P_add_to_force_vector_and_to_potential - * expansion_L2P_add_to_force_vector - * expansion_Evaluate_local_with_Y_already_computed - */ - void L2P(const CellClass* const local, FList<ParticleClass*>* const particles){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - typename FList<ParticleClass*>::BasicIterator iterTarget(*particles); - while( iterTarget.isValide() ){ - //printf("Morton %lld\n",local->getMortonIndex()); - - F3DPosition force_vector_in_local_base; - typename FFmbKernelsBlockBlas<ParticleClass,CellClass,TreeHeight>::Spherical spherical; - spherical = positionTsmphere( iterTarget.value()->getPosition() - local->getPosition()); - - /*printf("\t\t bodies_it_Get_p_position(&it) x = %lf \t y = %lf \t z = %lf \n", - (iterTarget.value()->getPosition()).getX(), - (iterTarget.value()->getPosition()).getY(), - (iterTarget.value()->getPosition()).getZ()); - printf("\t\t p_leaf_center x = %lf \t y = %lf \t z = %lf \n", - (local->getPosition()).getX(), - (local->getPosition()).getY(), - (local->getPosition()).getZ());*/ - /*printf("\t\t p_position_to_leaf_center x = %lf \t y = %lf \t z = %lf \n", - (iterTarget.value()->getPosition() - local->getPosition()).getX(), - (iterTarget.value()->getPosition() - local->getPosition()).getY(), - (iterTarget.value()->getPosition() - local->getPosition()).getZ());*/ - /*printf("\t\t phi = %lf \t cos = %lf \t sin = %lf \t r= %lf \n", - spherical.phi,spherical.cosTheta,spherical.sinTheta,spherical.r);*/ - - harmonicInnerThetaDerivated( spherical, FFmbKernelsBlockBlas<ParticleClass,CellClass,TreeHeight>::current_thread_Y, FFmbKernelsBlockBlas<ParticleClass,CellClass,TreeHeight>::current_thread_Y_theta_derivated); - - // The maximum degree used here will be P. - const FComplexe* p_Y_term = FFmbKernelsBlockBlas<ParticleClass,CellClass,TreeHeight>::current_thread_Y+1; - const FComplexe* p_Y_theta_derivated_term = FFmbKernelsBlockBlas<ParticleClass,CellClass,TreeHeight>::current_thread_Y_theta_derivated+1; - const FComplexe* p_local_exp_term = local->getLocal()+1; - - for (int j = 1 ; j <= FMB_Info_P ; ++j ){ - FComplexe exp_term_aux; - - // k=0: - // F_r: - exp_term_aux.setReal( (p_Y_term->getReal() * p_local_exp_term->getReal()) - (p_Y_term->getImag() * p_local_exp_term->getImag()) ); - exp_term_aux.setImag( (p_Y_term->getReal() * p_local_exp_term->getImag()) + (p_Y_term->getImag() * p_local_exp_term->getReal()) ); - - force_vector_in_local_base.setX( force_vector_in_local_base.getX() + j * exp_term_aux.getReal()); - // F_phi: k=0 => nothing to do for F_phi - // F_theta: - exp_term_aux.setReal( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getReal()) - (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getImag()) ); - exp_term_aux.setImag( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getImag()) + (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getReal()) ); - - force_vector_in_local_base.setY( force_vector_in_local_base.getY() + exp_term_aux.getReal()); - - - /*printf("\t j = %d \t exp_term_aux real = %lf imag = %lf \n", - j, - exp_term_aux.getReal(), - exp_term_aux.getImag());*/ - /*printf("\t\t\t p_Y_theta_derivated_term->getReal = %lf \t p_Y_theta_derivated_term->getImag = %lf \n", - p_Y_theta_derivated_term->getReal(),p_Y_theta_derivated_term->getImag());*/ - //printf("\t\t\t p_local_exp_term->getReal = %lf \t p_local_exp_term->getImag = %lf \n", - // p_local_exp_term->getReal(),p_local_exp_term->getImag()); - //printf("\t\t\t p_Y_term->getReal = %lf \t p_Y_term->getImag = %lf \n",p_Y_term->getReal(),p_Y_term->getImag()); - - //printf("[LOOP1] force_vector_in_local_base x = %lf \t y = %lf \t z = %lf \n", - // force_vector_in_local_base.getX(),force_vector_in_local_base.getY(),force_vector_in_local_base.getZ()); - - - ++p_local_exp_term; - ++p_Y_term; - ++p_Y_theta_derivated_term; - - - // k>0: - for (int k=1; k<=j ;++k, ++p_local_exp_term, ++p_Y_term, ++p_Y_theta_derivated_term){ - // F_r: - - exp_term_aux.setReal( (p_Y_term->getReal() * p_local_exp_term->getReal()) - (p_Y_term->getImag() * p_local_exp_term->getImag()) ); - exp_term_aux.setImag( (p_Y_term->getReal() * p_local_exp_term->getImag()) + (p_Y_term->getImag() * p_local_exp_term->getReal()) ); - - force_vector_in_local_base.setX(force_vector_in_local_base.getX() + 2 * j * exp_term_aux.getReal()); - // F_phi: - force_vector_in_local_base.setZ( force_vector_in_local_base.getZ() - 2 * k * exp_term_aux.getImag()); - // F_theta: - - /*printf("\t\t k = %d \t j = %d \t exp_term_aux real = %e imag = %e \n", - k,j, - exp_term_aux.getReal(), - exp_term_aux.getImag());*/ - //printf("\t\t\t p_Y_term->getReal = %e \t p_Y_term->getImag = %e \n",p_Y_term->getReal(),p_Y_term->getImag()); - //printf("\t\t\t p_local_exp_term->getReal = %e \t p_local_exp_term->getImag = %e \n",p_local_exp_term->getReal(),p_local_exp_term->getImag()); - - exp_term_aux.setReal( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getReal()) - (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getImag()) ); - exp_term_aux.setImag( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getImag()) + (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getReal()) ); - - force_vector_in_local_base.setY(force_vector_in_local_base.getY() + 2 * exp_term_aux.getReal()); - - /*printf("\t\t k = %d \t j = %d \t exp_term_aux real = %lf imag = %lf \n", - k,j, - exp_term_aux.getReal(), - exp_term_aux.getImag());*/ - /*printf("\t\t\t p_Y_theta_derivated_term->getReal = %lf \t p_Y_theta_derivated_term->getImag = %lf \n", - p_Y_theta_derivated_term->getReal(),p_Y_theta_derivated_term->getImag());*/ - /*printf("\t\t\t p_local_exp_term->getReal = %lf \t p_local_exp_term->getImag = %lf \n", - p_local_exp_term->getReal(),p_local_exp_term->getImag());*/ - - /*printf("[LOOP2] force_vector_in_local_base x = %lf \t y = %lf \t z = %lf \n", - force_vector_in_local_base.getX(),force_vector_in_local_base.getY(),force_vector_in_local_base.getZ());*/ - } - } - - /*printf("[END LOOP] force_vector_in_local_base x = %lf \t y = %lf \t z = %lf \n", - force_vector_in_local_base.getX(),force_vector_in_local_base.getY(),force_vector_in_local_base.getZ());*/ - - // We want: - gradient(POTENTIAL_SIGN potential). - // The -(- 1.0) computing is not the most efficient programming ... - //#define FMB_TMP_SIGN -(POTENTIAL_SIGN 1.0) - force_vector_in_local_base.setX( force_vector_in_local_base.getX() * (-1.0) / spherical.r); - force_vector_in_local_base.setY( force_vector_in_local_base.getY() * (-1.0) / spherical.r); - force_vector_in_local_base.setZ( force_vector_in_local_base.getZ() * (-1.0) / (spherical.r * spherical.sinTheta)); - //#undef FMB_TMP_SIGN - - ///////////////////////////////////////////////////////////////////// - - //spherical_position_Set_ph - //FMB_INLINE COORDINATES_T angle_Convert_in_MinusPi_Pi(COORDINATES_T a){ - FReal ph = FMath::Fmod(spherical.phi, 2*FMath::FPi); - if (ph > M_PI) ph -= 2*FMath::FPi; - if (ph < -M_PI + FMath::Epsilon) ph += 2 * FMath::Epsilon; - - //spherical_position_Set_th - FReal th = FMath::Fmod(FMath::ACos(spherical.cosTheta), 2*FMath::FPi); - if (th < 0.0) th += 2*FMath::FPi; - if (th > FMath::FPi){ - th = 2*FMath::FPi - th; - //spherical_position_Set_ph(p, spherical_position_Get_ph(p) + M_PI); - ph = FMath::Fmod(ph + FMath::FPi, 2*FMath::FPi); - if (ph > M_PI) ph -= 2*FMath::FPi; - if (ph < -M_PI + FMath::Epsilon) ph += 2 * FMath::Epsilon; - th = FMath::Fmod(th, 2*FMath::FPi); - if (th > M_PI) th -= 2*FMath::FPi; - if (th < -M_PI + FMath::Epsilon) th += 2 * FMath::Epsilon; - } - //spherical_position_Set_r - FReal rh = spherical.r; - if (spherical.r < 0){ - rh = -spherical.r; - //spherical_position_Set_ph(p, M_PI - spherical_position_Get_th(p)); - ph = FMath::Fmod(FMath::FPi - th, 2*FMath::FPi); - if (ph > M_PI) ph -= 2*FMath::FPi; - if (ph < -M_PI + FMath::Epsilon) ph += 2 * FMath::Epsilon; - //spherical_position_Set_th(p, spherical_position_Get_th(p) + M_PI); - th = FMath::Fmod(th + FMath::FPi, 2*FMath::FPi); - if (th < 0.0) th += 2*FMath::FPi; - if (th > FMath::FPi){ - th = 2*FMath::FPi - th; - //spherical_position_Set_ph(p, spherical_position_Get_ph(p) + M_PI); - ph = FMath::Fmod(ph + FMath::FPi, 2*FMath::FPi); - if (ph > M_PI) ph -= 2*FMath::FPi; - if (ph < -M_PI + FMath::Epsilon) ph += 2 * FMath::Epsilon; - th = FMath::Fmod(th, 2*FMath::FPi); - if (th > M_PI) th -= 2*FMath::FPi; - if (th < -M_PI + FMath::Epsilon) th += 2 * FMath::Epsilon; - } - } - - /*printf("[details] ph = %e , rh = %e , th = %e \n", - ph,rh,th);*/ - - - const FReal cos_theta = FMath::Cos(th); - const FReal cos_phi = FMath::Cos(ph); - const FReal sin_theta = FMath::Sin(th); - const FReal sin_phi = FMath::Sin(ph); - - /*printf("[details] cos_theta = %e \t cos_phi = %e \t sin_theta = %e \t sin_phi = %e \n", - cos_theta, cos_phi, sin_theta, sin_phi);*/ - /*printf("[force_vector_in_local_base] x = %lf \t y = %lf \t z = %lf \n", - force_vector_in_local_base.getX(),force_vector_in_local_base.getY(),force_vector_in_local_base.getZ());*/ - - F3DPosition force_vector_tmp; - - force_vector_tmp.setX( - cos_phi * sin_theta * force_vector_in_local_base.getX() + - cos_phi * cos_theta * force_vector_in_local_base.getY() + - (-sin_phi) * force_vector_in_local_base.getZ()); - - force_vector_tmp.setY( - sin_phi * sin_theta * force_vector_in_local_base.getX() + - sin_phi * cos_theta * force_vector_in_local_base.getY() + - cos_phi * force_vector_in_local_base.getZ()); - - force_vector_tmp.setZ( - cos_theta * force_vector_in_local_base.getX() + - (-sin_theta) * force_vector_in_local_base.getY()); - - /*printf("[force_vector_tmp] = %lf \t y = %lf \t z = %lf \n", - force_vector_tmp.getX(),force_vector_tmp.getY(),force_vector_tmp.getZ());*/ - - ///////////////////////////////////////////////////////////////////// - - //#ifndef _DIRECT_MATRIX_ - // When _DIRECT_MATRIX_ is defined, this multiplication is done in 'leaf_Sum_near_and_far_fields()' - force_vector_tmp *= iterTarget.value()->getPhysicalValue(); - //#endif - - /*printf("[force_vector_tmp] fx = %e \t fy = %e \t fz = %e \n", - force_vector_tmp.getX(),force_vector_tmp.getY(),force_vector_tmp.getZ());*/ - - iterTarget.value()->setForces( iterTarget.value()->getForces() + force_vector_tmp ); - - FReal potential; - expansion_Evaluate_local_with_Y_already_computed(local->getLocal(),&potential); - iterTarget.value()->setPotential(potential); - - /*printf("[END] fx = %e \t fy = %e \t fz = %e \n\n", - iterTarget.value()->getForces().getX(),iterTarget.value()->getForces().getY(),iterTarget.value()->getForces().getZ());*/ - //printf("p_potential = %lf\n", potential); - - iterTarget.progress(); - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - - void expansion_Evaluate_local_with_Y_already_computed(const FComplexe* local_exp, - FReal* const p_result){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - - FReal result = 0.0; - - FComplexe* p_Y_term = FFmbKernelsBlockBlas<ParticleClass,CellClass,TreeHeight>::current_thread_Y; - for(int j = 0 ; j<= FMB_Info_P ; ++j){ - // k=0 - (*p_Y_term) *= (*local_exp); - result += p_Y_term->getReal(); - //printf("\t\t p_Y_term->real = %e p_Y_term->imag = %e \t local_exp->real = %e local_exp->imag = %e \n", - // p_Y_term->getReal(), p_Y_term->getImag(), local_exp->getReal(), local_exp->getImag()); - ++p_Y_term; - ++local_exp; - - // k>0 - for (int k=1; k<=j ;++k, ++p_Y_term, ++local_exp){ - (*p_Y_term) *= (*local_exp); - result += 2 * p_Y_term->getReal(); - //printf("\t\t p_Y_term->real = %e p_Y_term->imag = %e \t local_exp->real = %e local_exp->imag = %e \n", - // p_Y_term->getReal(), p_Y_term->getImag(), local_exp->getReal(), local_exp->getImag()); - } - } - - *p_result = result; - - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - - - - - /** void bodies_Compute_direct_interaction ( - * bodies_t *FMB_RESTRICT p_b_target, - * bodies_t *FMB_RESTRICT p_b_src, - * bool mutual - * ) - * - */ - void P2P(FList<ParticleClass*>* const FRestrict targets, const FList<ParticleClass*>* const FRestrict sources, - FList<ParticleClass*>* FRestrict const* FRestrict directNeighbors, const int size) { - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - typename FList<ParticleClass*>::BasicIterator iterTarget(*targets); - while( iterTarget.isValide() ){ - - for(int idxDirectNeighbors = 0 ; idxDirectNeighbors < size ; ++idxDirectNeighbors){ - typename FList<ParticleClass*>::ConstBasicIterator iterSource(*directNeighbors[idxDirectNeighbors]); - while( iterSource.isValide() ){ - DIRECT_COMPUTATION_NO_MUTUAL_SOFT(&iterTarget.value(), - iterSource.value()); - iterSource.progress(); - } - } - - typename FList<ParticleClass*>::ConstBasicIterator iterSameBox(*sources); - while( iterSameBox.isValide() ){ - if(iterSameBox.value() != iterTarget.value()){ - DIRECT_COMPUTATION_NO_MUTUAL_SOFT(&iterTarget.value(), - iterSameBox.value()); - } - iterSameBox.progress(); - } - - //printf("x = %e \t y = %e \t z = %e \n",iterTarget.value()->getPosition().getX(),iterTarget.value()->getPosition().getY(),iterTarget.value()->getPosition().getZ()); - //printf("\t P2P fx = %e \t fy = %e \t fz = %e \n",iterTarget.value()->getForces().getX(),iterTarget.value()->getForces().getY(),iterTarget.value()->getForces().getZ()); - //printf("\t potential = %e \n",iterTarget.value()->getPotential()); - - iterTarget.progress(); - } - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } - void DIRECT_COMPUTATION_NO_MUTUAL_SOFT(ParticleClass** const target, const ParticleClass* const source){ - FTRACE( FTrace::Controller.enterFunction(FTrace::KERNELS, __FUNCTION__ , __FILE__ , __LINE__) ); - const FReal dx = (*target)->getPosition().getX() - source->getPosition().getX(); - const FReal dy = (*target)->getPosition().getY() - source->getPosition().getY(); - const FReal dz = (*target)->getPosition().getZ() - source->getPosition().getZ(); - - FReal inv_square_distance = 1.0/ (dx*dx + dy*dy + dz*dz + FFmbKernelsBlockBlas<ParticleClass,CellClass,TreeHeight>::FMB_Info_eps_soft_square); - FReal inv_distance = FMath::Sqrt(inv_square_distance); - inv_distance *= (*target)->getPhysicalValue() * source->getPhysicalValue(); - inv_square_distance *= inv_distance; - - (*target)->setForces( - (*target)->getForces().getX() + dx * inv_square_distance, - (*target)->getForces().getY() + dy * inv_square_distance, - (*target)->getForces().getZ() + dz * inv_square_distance - ); - - (*target)->setPotential( inv_distance + (*target)->getPotential()); - FTRACE( FTrace::Controller.leaveFunction(FTrace::KERNELS) ); - } -}; - - -template< class ParticleClass, class CellClass, int TreeHeight> -const FReal FFmbKernelsBlockBlas<ParticleClass,CellClass,TreeHeight>::PiArrayInner[4] = {0, FMath::FPiDiv2, FMath::FPi, -FMath::FPiDiv2}; - - -template< class ParticleClass, class CellClass, int TreeHeight> -const FReal FFmbKernelsBlockBlas<ParticleClass,CellClass,TreeHeight>::PiArrayOuter[4] = {0, -FMath::FPiDiv2, FMath::FPi, FMath::FPiDiv2}; - - - -#endif //FFMBKERNELSBLOCKBLAS_HPP - -// [--LICENSE--] diff --git a/Sources/ScalFmmConfig.h.cmake b/Sources/ScalFmmConfig.h.cmake deleted file mode 100644 index b0b9f85ca..000000000 --- a/Sources/ScalFmmConfig.h.cmake +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef SSCALFMMCONFIG_H -#define SSCALFMMCONFIG_H - -#cmakedefine FUSE_MKL_AS_BLAS - -#endif // CONFIG_H diff --git a/Sources/Utils/F3DPosition.hpp b/Sources/Utils/F3DPosition.hpp deleted file mode 100644 index ac48b007c..000000000 --- a/Sources/Utils/F3DPosition.hpp +++ /dev/null @@ -1,231 +0,0 @@ -#ifndef F3DPOSITION_HPP -#define F3DPOSITION_HPP -// /!\ Please, you must read the license at the bottom of this page - -// To get memcpy -#include <cstring> -#include "FGlobal.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class F3DPosition -* Please read the license -* -* This class is a 3D vector. It can be used as a position -* or as a 3d forces vector etc. -*/ -class F3DPosition{ -private: - FReal x; //< x position - FReal y; //< y position - FReal z; //< z position - -public: - /** Default constructor (sets position to 0/0/0) */ - F3DPosition() : x(0.0), y(0.0), z(0.0){ - } - - /** Constructor from values */ - F3DPosition(const FReal inX,const FReal inY,const FReal inZ) - : x(inX), y(inY), z(inZ){ - } - - /** Default destructor */ - virtual ~F3DPosition(){ - } - - /** - * Copy constructor - * @param other the source class to copy - */ - F3DPosition(const F3DPosition& other): x(other.x), y(other.y), z(other.z){ - } - - /** - * Copy constructor - * @param other the source class to copy - * @return this a reference to the current class - */ - F3DPosition& operator=(const F3DPosition& other){ - this->x = other.x; - this->y = other.y; - this->z = other.z; - return *this; - } - - /** - * Position setter - * @param other the source class to copy - * @return this a reference to the current class - */ - void setPosition(const FReal inX,const FReal inY,const FReal inZ){ - this->x = inX; - this->y = inY; - this->z = inZ; - } - - /** - * Get x - * @return this->x - */ - FReal getX() const{ - return this->x; - } - - /** - * Get y - * @return this->y - */ - FReal getY() const{ - return this->y; - } - - /** - * Get z - * @return this->z - */ - FReal getZ() const{ - return this->z; - } - - /** - * Set x - * @param the new x - */ - void setX(const FReal inX){ - this->x = inX; - } - - /** - * Set y - * @param the new y - */ - void setY(const FReal inY){ - this->y = inY; - } - - /** - * Set z - * @param the new z - */ - void setZ(const FReal inZ){ - this->z = inZ; - } - - /** - * Subtract to all dim the inValue - * @param inValue the value to substract - * @return the current object after being subtracted - */ - F3DPosition& operator-=(const FReal inValue){ - this->x -= inValue; - this->y -= inValue; - this->z -= inValue; - return *this; - } - - /** - * Affect to all dim the inValue - * @param inValue the value to afect - * @return the current object after being affected - */ - F3DPosition& operator+=(const FReal inValue){ - this->x += inValue; - this->y += inValue; - this->z += inValue; - return *this; - } - - /** - * Subtract to all dim the other position - * @param other the value to substract - * @return the current object after being subtracted - */ - F3DPosition& operator-=(const F3DPosition& other){ - this->x -= other.x; - this->y -= other.y; - this->z -= other.z; - return *this; - } - - /** - * Affect to all dim the other position - * @param other the value to afect - * @return the current object after being affected - */ - F3DPosition& operator+=(const F3DPosition& other){ - this->x += other.x; - this->y += other.y; - this->z += other.z; - return *this; - } - - /** - * Affect to all dim the other position - * @param other the value to afect - * @return the current object after being affected - */ - F3DPosition& operator*=(const FReal value){ - this->x *= value; - this->y *= value; - this->z *= value; - return *this; - } - -}; - -/** -* Operator F3Position minus FReal -* This substract inValue to all dimensions of the inPosition -* @param inPosition the position to compute -* @param inValue the value to decrease/substract position -* @return the resulting position -*/ -F3DPosition operator-(const F3DPosition& inPosition, const FReal inValue){ - F3DPosition position(inPosition); - position -= inValue; - return position; -} - -/** -* Operator F3Position plus FReal -* This affect from inValue all dimensions of the inPosition -* @param inPosition the position to compute -* @param inValue the value to increase/affect position -* @return the resulting position -*/ -F3DPosition operator+(const F3DPosition& inPosition, const FReal inValue){ - F3DPosition position(inPosition); - position += inValue; - return position; -} - -/** -* Operator F3Position minus F3Position -* This substract one from anther -* @param inPosition the position to reduce -* @param inOther the position to decrease/substract inPosition -* @return the resulting position -*/ -F3DPosition operator-(const F3DPosition& inPosition, const F3DPosition& inOther){ - F3DPosition position(inPosition); - position -= inOther; - return position; -} - -/** -* Operator F3Position plus F3Position -* This substract one from anther -* @param inPosition the position to reduce -* @param inOther the position to increase inPosition -* @return the resulting position -*/ -F3DPosition operator+(const F3DPosition& inPosition, const F3DPosition& inOther){ - F3DPosition position(inPosition); - position += inOther; - return position; -} - -#endif //F3DPOSITION_HPP - -// [--LICENSE--] diff --git a/Sources/Utils/FAbstractApplication.hpp b/Sources/Utils/FAbstractApplication.hpp deleted file mode 100644 index f12e9619f..000000000 --- a/Sources/Utils/FAbstractApplication.hpp +++ /dev/null @@ -1,212 +0,0 @@ -#ifndef FABSTRACTAPPLICATION_HPP -#define FABSTRACTAPPLICATION_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include <sstream> -#include <iostream> -#include <string.h> - -#include "FAssertable.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FAbstractApplication -* Please read the license -* -* This class is an interface for main application. -* It represents the core of the system -* Only one app can be instancied by program. -* -* @warning you have to implement run() and call execute to start the app -* -* Please refere to testApplication.cpp to see an example. -* <code> -* </code> -*/ -class FAbstractApplication { -private: - const int argc; //< argc from command line - - char ** const argv; //< argv from command line - -protected: - /** - * This will be called as the main method - * @warning Must be impleted in the derived class - */ - virtual void run() = 0; - - /** - * This function is called before the run if the process is the master one - */ - virtual void initMaster(){} - - /** - * This function is called before the run if the process is a slave - */ - virtual void initSlave(){} - - /** - * Send data to another process - */ - virtual void sendData(const int inReceiver, const int inSize, void* const inData, const int inTag) = 0; - - /** - * Receive from any process - */ - virtual void receiveData(const int inSize, void* const inData, int* const inSource, int* const inTag, int* const inFilledSize) = 0; - -private: - - /** Forbiden (private) default constructor */ - FAbstractApplication():argc(0), argv(0){} - - /** Forbiden (private) copy constructor */ - FAbstractApplication(const FAbstractApplication&):argc(0), argv(0){} - - /** Forbiden (private) copy */ - FAbstractApplication& operator=(const FAbstractApplication&){return *this;} - -public: - /** - * Constructor - * @param inArgc argc from command line - * @param inArgv argv from command line - * This will also set the current app in the assert system - */ - FAbstractApplication(const int inArgc, char ** const inArgv ) - : argc(inArgc), argv(inArgv) { - FAssertable::SetCurrentApp(this); - } - - /** Destructor */ - virtual ~FAbstractApplication(){} - - /** - * This function has to be called to execute the process run - * @return 0 if success - */ - int execute(){ - if( isMaster() ) initMaster(); - else initSlave(); - run(); - return 0; - } - - /** - * To get the current process id - * @return the process numeber [0 ; processCount [ - */ - virtual int processId() const = 0; - - /** - * To get the number of process - * @return process count - */ - virtual int processCount() const = 0; - - /** - * To make a barrier between process - */ - virtual void processBarrier() const = 0; - - /** - * To kill all process - * @param inErrorCode the error to return to OS (default is 1) - */ - virtual void abort(const int inErrorCode = 1) const = 0; - - /** - * This function has to be used to know if the current app is the master - * @return true if id() == 0 - */ - bool isMaster() const { - return !processId(); - } - - /** - * This function has to be used to know if the current app is alone - * @return true if processCount() == 1 - */ - bool isAlone() const { - return processCount() == 1; - } - - /** - * This function has to be used to know if the current app is a slave - * @return true if id() != 0 - */ - bool isSlave() const { - return processId(); - } - - /** - * This function gives the number of parameters (argc) - * @return argc - */ - int userParemetersCount() const{ - return this->argc; - } - - /** - * This function gives a parameter - * @parameter inArg parameter position has to be strictly less than argc/userParemetersCount - * @return argv[inArg] - */ - const char* userParemeterAt(const int inArg) const{ - return this->argv[inArg]; - } - - /** - * This function gives a parameter in a standart type - * @parameter inArg parameter position has to be strictly less than argc/userParemetersCount - * @return argv[inArg] in the template VariableType form - * @warning VariableType need to work with istream >> operator - * <code> const int argInt = userParemetersAt<int>(1,-1); </code> - */ - template <class VariableType> - const VariableType userParemeterAt(const int inArg, const VariableType& defaultValue = VariableType()) const{ - std::istringstream iss(this->argv[inArg],std::istringstream::in); - VariableType value; - iss >> value; - if( /*iss.tellg()*/ iss.eof() ) return value; - return defaultValue; - } - - /** - * This function gives the parameter in a standart type after a key parameter - * Do not use pointer in template type! - * @parameter inArg parameter key - * @return argv[inArg.position + 1] in the template VariableType form - * @warning VariableType need to work with istream >> operator - * <code> const int argInt = userParemetersAt<int>(1,-1); </code> - */ - template <class VariableType> - const VariableType userParemeterFromKey(const char* const inKey, const VariableType& defaultValue = VariableType(), bool* const inState = 0) const{ - const int keysArgc= this->argc - 1; - // loop from 1 to argc 1 - for(int indexArg = 1 ; indexArg < keysArgc ; ++indexArg){ - // if argv == inArg - if(strcmp(this->argv[indexArg] , inKey) == 0){ - // the argv + 1 => variable to use - std::istringstream iss(this->argv[indexArg + 1],std::istringstream::in); - VariableType value; - iss >> value; - // if we can cast to the template type - if( iss.eof() ){ - if( inState ) *inState = true; - return value; - } - break; - } - } - // cannot cast to template or key not found - if( inState ) *inState = false; - return defaultValue; - } - -}; - -#endif //FABSTRACTAPPLICATION_HPP - -// [--LICENSE--] diff --git a/Sources/Utils/FAssertable.cpp b/Sources/Utils/FAssertable.cpp deleted file mode 100644 index 6d3f7589b..000000000 --- a/Sources/Utils/FAssertable.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "FAssertable.hpp" -#include "FAbstractApplication.hpp" - -/** -* Current application -*/ -FAbstractApplication* FAssertable::CurrentApp(0); - -// Simply quit the current app -void FAssertable::exitApplication(const int inExitCode) const{ - if(CurrentApp) CurrentApp->abort(inExitCode); -} - - - - diff --git a/Sources/Utils/FAssertable.hpp b/Sources/Utils/FAssertable.hpp deleted file mode 100644 index 87f9c1816..000000000 --- a/Sources/Utils/FAssertable.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef FASSERTABLE_HPP -#define FASSERTABLE_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include <sstream> -#include <iostream> - -class FAbstractApplication; - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FAssertable -* Please read the license -* -* This class is an interface for managing error. -* -* Please refere to testAssert.cpp to see an example -* <code> -* </code> -*/ -class FAssertable { -private: - static FAbstractApplication* CurrentApp; //< You must have only one app - - /** - * Called by Fapplication instance to set the current app - * @param inCurrentApp current app - */ - static void SetCurrentApp(FAbstractApplication* const inCurrentApp){ - CurrentApp = inCurrentApp; - } - - /** To set CurrentApp */ - friend class FAbstractApplication; - - /** To quit current application */ - void exitApplication(const int inExitCode) const; - -protected: - /** Empty Destructor */ - virtual ~FAssertable(){} - - /** - * to write debug data with line & file - * @param inTest if false, application will stop - * @param inMessage a message - from any type - to print - * @param inLinePosition line number - * @param inFilePosition file name - * - * <code> assert(toto == titi, "toto is not equal titi!", __LINE__, __FILE__); </code> - * - * To prevent use from multiple thread we use a ostringstream before printing - */ - template <class Tmess, class Tline, class Tfile> - void assert(const bool inTest, const Tmess& inMessage, const Tline& inLinePosition, const Tfile& inFilePosition, const int inExitCode = 1) const { - if(!inTest){ - calledBeforeExit(); - - std::ostringstream oss; - oss << "Error in " << inFilePosition << " at line " << inLinePosition <<" :\n"; - oss << inMessage << "\n"; - - std::cerr << oss.str(); - exitApplication(inExitCode); - } - } - - /** - * May be implemented in the derived class to know when app will quit - */ - virtual void calledBeforeExit() const {} - -}; - -#endif //FASSERTABLE_HPP - -// [--LICENSE--] diff --git a/Sources/Utils/FBlas.hpp b/Sources/Utils/FBlas.hpp deleted file mode 100644 index 2f3a82295..000000000 --- a/Sources/Utils/FBlas.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef FBLAS_HPP -#define FBLAS_HPP - -/////////////////////////////////////////////////////// -// Manage Blas Version -/////////////////////////////////////////////////////// - -#include "ScalFmmConfig.h" - -#ifdef FUSE_MKL_AS_BLAS -#include <mkl_cblas.h> -#else -#include <cblas.h> -#endif - -/////////////////////////////////////////////////////// -// GEMV -/////////////////////////////////////////////////////// - -template <typename T> -void cblas_gemv(const CBLAS_ORDER order , - const CBLAS_TRANSPOSE TransA , const int M , const int N , - const void *alpha , const void *A , const int lda , - const void *X , const int incX , const void *beta , - void *Y , const int incY){ - T t; - t.you_cannot_use_this_function_with_this_type(); -} - -template <> -void cblas_gemv<double>(const CBLAS_ORDER order , - const CBLAS_TRANSPOSE TransA , const int M , const int N , - const void *alpha , const void *A , const int lda , - const void *X , const int incX , const void *beta , - void *Y , const int incY){ - cblas_zgemv(order,TransA,M,N,alpha,A,lda,X,incX,beta,Y,incY); -} - -template <> -void cblas_gemv<float>(const CBLAS_ORDER order , - const CBLAS_TRANSPOSE TransA , const int M , const int N , - const void *alpha , const void *A , const int lda , - const void *X , const int incX , const void *beta , - void *Y , const int incY){ - cblas_cgemv(order,TransA,M,N,alpha,A,lda,X,incX,beta,Y,incY); -} - - -/////////////////////////////////////////////////////// -// Dotu -/////////////////////////////////////////////////////// - -template <typename T> -void cblas_dotu_sub( const int N , const void *X , const int incX , - const void *Y , const int incY , void *dotu){ - T t; - t.you_cannot_use_this_function_with_this_type(); -} - -template <> -void cblas_dotu_sub<double>(const int N , const void *X , const int incX , - const void *Y , const int incY , void *dotu){ - cblas_zdotu_sub(N,X,incX,Y,incY,dotu); -} - -template <> -void cblas_dotu_sub<float>(const int N , const void *X , const int incX , - const void *Y , const int incY , void *dotu){ - cblas_cdotu_sub(N,X,incX,Y,incY,dotu); -} - -#endif //FBLAS_HPP - diff --git a/Sources/Utils/FComplexe.hpp b/Sources/Utils/FComplexe.hpp deleted file mode 100644 index 8749c1287..000000000 --- a/Sources/Utils/FComplexe.hpp +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef FCOMPLEXE_HPP -#define FCOMPLEXE_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "FMath.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class -* Please read the license -* -* Propose basic complexe class. -* Do not modify the attributes of this class. -* It can be passed to blas fonction and has to be -* 2 x real size only. -*/ -class FComplexe { - FReal real; //< Real - FReal imag; //< Imaginary - -public: - /** Default Constructor (set real&imaginary to 0) */ - FComplexe() : real(0),imag(0){ - } - - /** Constructor with values - * @param inImag the imaginary - * @param inReal the real - */ - FComplexe(const FReal inImag, const FReal inReal) - : real(inReal),imag(inImag){ - } - - /** Copy constructor */ - FComplexe(const FComplexe& other) - : real(other.real), imag(other.imag){ - } - - /** Copy operator */ - FComplexe& operator=(const FComplexe& other){ - this->imag = other.imag; - this->real = other.real; - return *this; - } - - /** Equality operator */ - bool operator==(const FComplexe& other){ - return FMath::LookEqual(this->imag,other.imag) - && FMath::LookEqual(this->real,other.real); - } - - /** Different equal */ - bool operator!=(const FComplexe& other){ - return !(*this == other); - } - - /** Get imaginary */ - FReal getImag() const{ - return this->imag; - } - - /** Get real */ - FReal getReal() const{ - return this->real; - } - - /** Set Imaginary */ - void setImag(const FReal inImag) { - this->imag = inImag; - } - - /** Set Real */ - void setReal(const FReal inReal) { - this->real = inReal; - } - - /** - * Operator += - * in real with other real, same for imag - * @param other the complexe to use data - */ - FComplexe& operator+=(const FComplexe& other){ - this->real += other.real; - this->imag += other.imag; - return *this; - } - - /** Inc real and imaginary by values - * @param inIncReal to inc the real - * @param inIncImag to inc the imag - */ - void inc(const FReal inIncReal, const FReal inIncImag){ - this->real += inIncReal; - this->imag += inIncImag; - } - - /** Inc real by FReal - * @param inIncReal to inc the real - */ - void incReal(const FReal inIncReal){ - this->real += inIncReal; - } - - /** Inc imaginary by FReal - * @param inIncImag to inc the imag - */ - void incImag(const FReal inIncImag){ - this->imag += inIncImag; - } - - /** Dec real by FReal - * @param inDecReal to dec the real - */ - void decReal(const FReal inIncReal){ - this->real -= inIncReal; - } - - /** Dec imaginary by FReal - * @param inDecImag to dec the imag - */ - void decImag(const FReal inIncImag){ - this->imag -= inIncImag; - } - - /** Mul real and imaginary by a FReal - * @param inValue the coef to mul data - */ - void mulRealAndImag(const FReal inValue){ - this->imag *= inValue; - this->real *= inValue; - } - - /** Mul a complexe by another "c*=c2" */ - FComplexe& operator*=(const FComplexe& other){ - const FReal tempReal = this->real; - this->real = (tempReal * other.real) - (this->imag * other.imag); - this->imag = (tempReal * other.imag) + (this->imag * other.real); - return *this; - } -}; - -/** Global operator Mul a complexe by another "c=c1*c2" */ -FComplexe operator*=(const FComplexe& first, const FComplexe& second){ - const FComplexe result( - (first.getReal() * second.getImag()) + (first.getImag() * second.getReal()), - (first.getReal() * second.getReal()) - (first.getImag() * second.getImag()) - ); - return result; -} - -#endif //FCOMPLEXE_HPP - -// [--LICENSE--] diff --git a/Sources/Utils/FConvert.hpp b/Sources/Utils/FConvert.hpp deleted file mode 100644 index cd7df3fe8..000000000 --- a/Sources/Utils/FConvert.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef FCONVERT_HPP -#define FCONVERT_HPP - -#include "../Containers/FTreeCoordinate.hpp" -#include "../Utils/F3DPosition.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class -* Please read the license -* This class proposes some convertion functions -* FConvert is used here as a namespace. -*/ -class FConvert { -public : - /** To get spatial position (F3DPosition) from morton data - * @param inIndex the morton index of the object - * @param inLevel the level of the current object - * @param inWidthAtLevel the width of the box at this level - * return outPosition the result - */ - static F3DPosition MortonToPosition(const MortonIndex inIndex, const int inLevel, const FReal inWidthAtLevel){ - FTreeCoordinate treePosition; - treePosition.setPositionFromMorton(inIndex, inLevel); - - F3DPosition outPosition( - treePosition.getX() * inWidthAtLevel + inWidthAtLevel/2, - treePosition.getY() * inWidthAtLevel + inWidthAtLevel/2, - treePosition.getZ() * inWidthAtLevel + inWidthAtLevel/2 - ); - - return outPosition; - } -}; - -#endif - diff --git a/Sources/Utils/FDebug.cpp b/Sources/Utils/FDebug.cpp deleted file mode 100644 index 5ceb2e00c..000000000 --- a/Sources/Utils/FDebug.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "FDebug.hpp" -#ifdef FUSE_DEBUG - -/** -* Singleton debug -*/ -FDebug FDebug::Controller; - - - -#endif // FUSE_DEBUG - diff --git a/Sources/Utils/FDebug.hpp b/Sources/Utils/FDebug.hpp deleted file mode 100644 index df21ea5fe..000000000 --- a/Sources/Utils/FDebug.hpp +++ /dev/null @@ -1,187 +0,0 @@ -#ifndef FDEBUG_HPP -#define FDEBUG_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "FGlobal.hpp" - -#ifndef FUSE_DEBUG - -#define FDEBUG( X ) -#define FDEBUG( X ) - -#else - -#define FDEBUG( X ) X -#define FDEBUG( X ) X - -#include <iostream> -#include <fstream> -#include <sstream> - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FDebug -* Please read the license -* -* This class is used to print debug data durint processing. -* You have to use the DEBUG macro as shown in the example. -* -* <code> -* FDEBUG( FDebug::Controller.writeFromLine("hello World", __LINE__, __FILE__); ) <br> -* FDEBUG( FDebug::Controller << "I want to debug " << toto << "\n"; ) -* </code> -*/ -class FDebug{ -private: - std::ostream* stream; //< Standart c++ ostream - - /** Default constructor forbiden */ - FDebug() : stream(&std::cout) { - } - - /** Default destructor forbiden */ - virtual ~FDebug(){ - close(); - } - - /** - * Close the current debug stream - * dealloc the stream if differents from cout. - * after this call stream is useless - */ - void close(){ - flush(); - if(this->stream != &std::cout) delete(this->stream); - } - - /** - * Copy constructor forbiden - * @param other the source class to copy - */ - FDebug(const FDebug& ){} - - /** - * Copy constructor forbiden - * @param other the source class to copy - * @return this a reference to the current class - */ - FDebug& operator=(const FDebug& ){ - return *this; - } - - -public: - static FDebug Controller; //< Singleton - - /** - * To set the debug stream to write into a file - * @param filename the file to write - */ - void writeToFile(const char* const filename){ - close(); - - std::ofstream* const file = new std::ofstream(); - file->open(filename); - - this->stream = file; - } - - /** - * To set the debug stream to write to std::cout - */ - void writeToCout(){ - close(); - this->stream = &std::cout; - } - - /** - * stream operator to print debug data - * @param inMessage a message - from any type - to print - * @return current FDebug - */ - template <class T> - FDebug& operator<<(const T& inMessage){ - return write(inMessage); - } - - /** - * to write debug data - * @param inMessage a message - from any type - to print - * @return current FDebug - */ - template <class T> - FDebug& write(const T& inMessage){ - (*this->stream) << inMessage; - return *this; - } - - /** Flush data into stream */ - void flush(){ - this->stream->flush(); - } - - enum FlushType{ - Flush, - FlushWithLine - }; - - /** - * stream operator to flush debug data - * @param inType flush type - * @return current FDebug - */ - FDebug& write(const FlushType inType){ - if(inType == FlushWithLine) (*this->stream) << '\n'; - flush(); - return *this; - } - - /** - * to write debug data with line & file - * @param inMessage a message - from any type - to print - * @param inLinePosition line number - * @param inFilePosition file name - * @return current FDebug - * - * <code> FDebug::Controller.writeFromLine("hello World", __LINE__, __FILE__); </code> - * - * To prevent use from multiple thread we use a ostringstream before printing - */ - template <class T, class Tline, class Tfile> - FDebug& writeFromLine(const T& inMessage, const Tline& inLinePosition, const Tfile& inFilePosition){ - std::ostringstream oss; - oss << "Message from " << inFilePosition << " (at line " << inLinePosition <<")\n"; - oss << ">> " << inMessage << "\n"; - - (*this->stream) << oss.str(); - return *this; - } - - /** - * to write debug data with line & file - * @param inVariable variable name - * @param inValue variable value - * @param inLinePosition line number - * @param inFilePosition file name - * @return current FDebug - * - * <code> FDebug::Controller.writeVariableFromLine( "toto", toto, __LINE__, __FILE__); </code> - * - * To prevent use from multiple thread we use a ostringstream before printing - */ - template <class T, class Tline, class Tfile> - FDebug& writeVariableFromLine(const char* const inVariable, const T& inValue, const Tline& inLinePosition, const Tfile& inFilePosition){ - std::ostringstream oss; - oss << "[Value] " << inVariable << " = " << inValue << " at line " << inLinePosition <<" (file " << inFilePosition << ")\n"; - - (*this->stream) << oss.str(); - return *this; - } - -}; - -#endif //FUSE_DEBUG - -#endif //FDEBUG_HPP - -// [--LICENSE--] diff --git a/Sources/Utils/FGlobal.hpp b/Sources/Utils/FGlobal.hpp deleted file mode 100644 index 778090340..000000000 --- a/Sources/Utils/FGlobal.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef FGLOBAL_HPP -#define FGLOBAL_HPP - -/////////////////////////////////////////////////////// -// Operating System -/////////////////////////////////////////////////////// - -#if defined(_WIN32) || defined(ming) - #define WINDOWS -#else - #define POSIX -#endif - -/////////////////////////////////////////////////////// -// Debug -/////////////////////////////////////////////////////// - -// Uncomment the next line to use debug mode -#define FUSE_DEBUG - -/////////////////////////////////////////////////////// -// Debug -/////////////////////////////////////////////////////// - -// Uncomment the next line to use trace mode -//#define FUSE_TRACE - -/////////////////////////////////////////////////////// -// MPI -/////////////////////////////////////////////////////// - -//#define FUSE_MPI - -/////////////////////////////////////////////////////// -// Threads -/////////////////////////////////////////////////////// - -static const int FThreadNumbers = 4; - -/////////////////////////////////////////////////////// -// Types -/////////////////////////////////////////////////////// - -typedef double FReal; - -/////////////////////////////////////////////////////// -// Restrict -/////////////////////////////////////////////////////// - -#ifdef WINDOWS - #define FRestrict __restrict -#else - #define FRestrict __restrict__ -#endif - -#endif //FGLOBAL_HPP - diff --git a/Sources/Utils/FMath.hpp b/Sources/Utils/FMath.hpp deleted file mode 100644 index ab464fbf4..000000000 --- a/Sources/Utils/FMath.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef FMATH_HPP -#define FMATH_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include <math.h> -#include "FGlobal.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class -* Please read the license -* -* Propose basic math functions or indirections to std math. -*/ -struct FMath{ - static const double FPi; //< Pi constant - static const double FPiDiv2; //< Pi/2 constant - static const double Epsilon; //< Epsilon - - /** To get absolute value */ - template <class NumType> - static NumType Abs(const NumType inV){ - return (inV < 0 ? -inV : inV); - } - - /** To get max between 2 values */ - template <class NumType> - static NumType Max(const NumType inV1, const NumType inV2){ - return (inV1 > inV2 ? inV1 : inV2); - } - - /** To get min between 2 values */ - template <class NumType> - static NumType Min(const NumType inV1, const NumType inV2){ - return (inV1 < inV2 ? inV1 : inV2); - } - - /** To know if 2 values seems to be equal */ - template <class NumType> - static bool LookEqual(const NumType inV1, const NumType inV2){ - /*const FReal relTol = 0.00001; - const FReal absTol = 0.00001; - return (Abs(inV1 - inV2) <= Max(absTol, relTol * Max(Abs(inV1), Abs(inV2))));*/ - return Abs(inV1 - inV2) <= (Abs(inV1 < Abs(inV2) ? Abs(inV2) : Abs(inV1)) * 0.00001); - } - - /** To get floor of a FReal */ - static FReal dfloor(const FReal inValue){ - return floor(inValue); - } - - /** To get pow */ - template <class NumType> - static NumType pow(const NumType inValue, long power){ - NumType result = 1; - while(power-- > 0) result *= inValue; - return result; - } - - /** To know if a value is between two others */ - template <class NumType> - static bool Between(const NumType inValue, const NumType inMin, const NumType inMax){ - return ( inMin <= inValue && inValue < inMax ); - } - - /** To get sqrt of a FReal */ - static FReal Sqrt(const FReal inValue){ - return sqrt(inValue); - } - - /** To get atan2 of a 2 FReal */ - static FReal Atan2(const FReal inValue1,const FReal inValue2){ - return atan2(inValue1,inValue2); - } - - /** To get sqrt of a FReal */ - static FReal Sin(const FReal inValue){ - return sin(inValue); - } - - /** To get cos of a FReal */ - static FReal Cos(const FReal inValue){ - return cos(inValue); - } - - /** To get acos of a FReal */ - static FReal ACos(const FReal inValue){ - return acos(inValue); - } - - /** To get atan2 of a 2 FReal */ - static FReal Fmod(const FReal inValue1,const FReal inValue2){ - return fmod(inValue1,inValue2); - } -}; - -const double FMath::FPi = M_PI; -const double FMath::FPiDiv2 = M_PI_2; -const double FMath::Epsilon = 0.00000000000000000001; - -#endif //FMATH_HPP - -// [--LICENSE--] diff --git a/Sources/Utils/FMpiApplication.hpp b/Sources/Utils/FMpiApplication.hpp deleted file mode 100644 index 51ffcc498..000000000 --- a/Sources/Utils/FMpiApplication.hpp +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef FMPIAPPLICATION_HPP -#define FMPIAPPLICATION_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include <mpi.h> - -#include "FAbstractApplication.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FMpiApplication -* Please read the license -* -* This class is an implementation of the abstract application with mpi -* -* @warning you have to implement run() and call execute to start the app -* -* Please refere to testApplication.cpp to see an example -* <code> -* </code> -*/ -class FMpiApplication : public FAbstractApplication { -protected: - /** - * This will be called as the main method - * @warning Must be impleted in the derived class - */ - virtual void run() = 0; - - - void sendData(const int inReceiver, const int inSize, void* const inData, const int inTag){ - MPI_Request request; - MPI_Isend(inData, inSize, MPI_CHAR , inReceiver, inTag, MPI_COMM_WORLD, &request); - } - - void receiveData(const int inSize, void* const inData, int* const inSource, int* const inTag, int* const inFilledSize){ - MPI_Status status; - MPI_Recv(inData, inSize, MPI_CHAR, MPI_ANY_SOURCE, MPI_ANY_TAG,MPI_COMM_WORLD, &status); - *inSource = status.MPI_SOURCE; - *inTag = status.MPI_TAG; - MPI_Get_count(&status,MPI_CHAR,inFilledSize); - } - -public: - /** - * Constructor - * @param inArgc argc from command line - * @param inArgv argv from command line - */ - FMpiApplication(int inArgc, char ** inArgv ) - : FAbstractApplication(inArgc,inArgv) { - MPI_Init(&inArgc,&inArgv); - } - - /** Destructor */ - virtual ~FMpiApplication(){ - MPI_Finalize(); - } - - /** - * To get the current process id - * @return the process numeber [0 ; processCount [ - */ - int processId() const { - int id; - MPI_Comm_rank(MPI_COMM_WORLD,&id); - return id; - } - - /** - * To get the number of process - * @return process count - */ - int processCount() const { - int count; - MPI_Comm_size(MPI_COMM_WORLD,&count); - return count; - } - - /** - * To make a barrier between process - */ - void processBarrier() const{ - MPI_Barrier(MPI_COMM_WORLD); - } - - /** - * To kill all process - * @param inErrorCode the error to return to OS (default is 1) - */ - void abort(const int inErrorCode = 1) const { - MPI_Abort(MPI_COMM_WORLD, inErrorCode); - } - - - -}; - -#endif //FMPIAPPLICATION_HPP - -// [--LICENSE--] diff --git a/Sources/Utils/FSingleApplication.hpp b/Sources/Utils/FSingleApplication.hpp deleted file mode 100644 index 489e1c8b4..000000000 --- a/Sources/Utils/FSingleApplication.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef FSINGLEAPPLICATION_HPP -#define FSINGLEAPPLICATION_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include <stdlib.h> - - -#include "FAbstractApplication.hpp" - - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FSingleApplication -* Please read the license -* -* This class is an application of abstract application with as a standalone process -* -* @warning you have to implement run() and call execute to start the app -* -* Please refere to testApplication.cpp to see an example -* <code> -* </code> -*/ -class FSingleApplication : public FAbstractApplication { -protected: - /** - * This will be called as the main method - * @warning Must be impleted in the derived class - */ - virtual void run() = 0; - - void sendData(const int, const int, void* const, const int ){ - } - - - void receiveData(const int, void* const, int* const inSource, int* const inTag, int* const inFilledSize){ - *inSource = 0; - *inTag = 0; - *inFilledSize = 0; - } - -public: - /** - * Constructor - * @param inArgc argc from command line - * @param inArgv argv from command line - */ - FSingleApplication(const int inArgc, char ** const inArgv ) - : FAbstractApplication(inArgc,inArgv) { - } - - /** Destructor */ - virtual ~FSingleApplication(){} - - /** - * To get the current process id - * @return the process numeber [0 ; processCount [ - */ - int processId() const { - return 0; - } - - /** - * To get the number of process - * @return process count - */ - int processCount() const { - return 1; - } - - /** - * To make a barrier between process - */ - void processBarrier() const{} - - /** - * To kill all process - * @param inErrorCode the error to return to OS (default is 1) - */ - void abort(const int inErrorCode = 1) const { - exit(inErrorCode); - } - -}; - -#endif //FSINGLEAPPLICATION_HPP - -// [--LICENSE--] diff --git a/Sources/Utils/FTic.hpp b/Sources/Utils/FTic.hpp deleted file mode 100644 index 51fe87db1..000000000 --- a/Sources/Utils/FTic.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef FTIC_HPP -#define FTIC_HPP - -#include <time.h> - -#include "FGlobal.hpp" - -#if defined(WINDOWS) - #include <windows.h> -#else - #ifndef POSIX - #warning Posix used withoug being explicitly defined - #endif - #include <sys/time.h> -#endif - - -/** @author Berenger Bramas (berenger.bramas@inria.fr) - * This class is a easy to use time counter - * With it you can very easyli estimate elapsed - * time between two moments - * <code> - * FTic counter;<br> - * counter.tic();<br> - * //...<br> - * counter.tac();<br> - * counter.elapsed(); //> time in s<br> - * </code> - */ -class FTic { -private: - double start; //< start time (tic) - double end; //< stop time (tac) - -public: - /** Constructor */ - FTic() : start(0.0), end(0.0) { - } - - /** Tic : start <= current time */ - void tic(){ - this->start = FTic::GetTime(); - } - - /** Tac : end <= current time */ - void tac(){ - this->end = FTic::GetTime(); - } - - /** Return end - start - * @return the time elapsed between tic & tac in second */ - double elapsed() const{ - return this->end - this->start; - } - - /** Global get time - * @return a global time - * GetTickCount on windows - * gettimeofday on linux - */ - static double GetTime(){ -#ifdef WINDOWS - return static_cast<double>(GetTickCount())/1000.0; -#else - timeval t; - gettimeofday(&t, NULL); - return (t.tv_sec) + (t.tv_usec/1000000.0); -#endif - } -}; - - -#endif - diff --git a/Sources/Utils/FTrace.cpp b/Sources/Utils/FTrace.cpp deleted file mode 100644 index 3f4a7eb94..000000000 --- a/Sources/Utils/FTrace.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "FTrace.hpp" -#ifdef FUSE_TRACE - -/** -* Singleton debug -*/ -FTrace FTrace::Controller; - - - -#endif // FUSE_TRACE - diff --git a/Sources/Utils/FTrace.hpp b/Sources/Utils/FTrace.hpp deleted file mode 100644 index 2c6027ddd..000000000 --- a/Sources/Utils/FTrace.hpp +++ /dev/null @@ -1,231 +0,0 @@ -#ifndef FTRACE_HPP -#define FTRACE_HPP -// /!\ Please, you must read the license at the bottom of this page - -#include "FGlobal.hpp" - -#ifndef FUSE_TRACE - -#define FTRACE( X ) - -#else - -#define FTRACE( X ) X - -#include <iostream> -#include <fstream> -#include <sstream> - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FTrace -* Please read the license -* -* This class is used to print trace data durint processing. -* You have to use the FTRACE macro as shown in the example. -* -* <code> -* FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); -* ... -* FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); -* </code> -*/ -class FTrace{ -private: - /////////////////////////////////////////////////// - // Constant & config - /////////////////////////////////////////////////// - - static const int MaxDeep = 4; //< Max deep enabled - static const int PrintParameters = true; //< Enable parameters printing - static const int PrintLineNumber = true; //< Enable parameters printing - static const int PrintFileName = true; //< Enable parameters printing - - /** This tags are used to enable/disable - * trace depending on the functions that - * calls it. - */ - enum Tags { - FMM = 1, - FILE = 2, - KERNELS = 4, - UTILS = 8, - UNDEFINED = 16 - }; - - static const int EnabledTags = FMM | FILE ; //< Which tag can print - - /////////////////////////////////////////////////// - // Real class - /////////////////////////////////////////////////// - - int currentDeep; //< Current deep in the code - std::ostream* stream; //< Standart c++ ostream - - /** Default constructor forbiden */ - FTrace() : stream(&std::cout), currentDeep(0) { - } - - /** Default destructor forbiden */ - virtual ~FTrace(){ - close(); - } - - /** - * Close the current debug stream - * dealloc the stream if differents from cout. - * after this call stream is useless - */ - void close(){ - flush(); - if(this->stream != &std::cout) delete(this->stream); - } - - /** - * Copy constructor forbiden - * @param other the source class to copy - */ - FTrace(const FTrace& ){} - - /** - * Copy constructor forbiden - * @param other the source class to copy - * @return this a reference to the current class - */ - FTrace& operator=(const FTrace& ){ - return *this; - } - - /** Print tab depending on the deep - * - */ - void printTab(){ - for(int idxDeep = 0 ; idxDeep < currentDeep ; ++idxDeep ){ - (*this->stream) << "\t"; - } - } - -public: - static FTrace Controller; //< Singleton - - /** Call this function when entering a function - * @param inTag the tag at this position - * @param inName the function's name - * @param inFile the file's name - * @param inLine the line number - * <code> - * FTRACE( FTrace::Controller.enterFunction(FTrace::FMM, __FUNCTION__ , __FILE__ , __LINE__) ); - * </code> - */ - template <class T, class TF, class TL> - FTrace& enterFunction(const Tags inTag, const T& inName, const TF& inFile , const TL& inLine){ - if(inTag & EnabledTags){ - if(currentDeep < MaxDeep){ - printTab(); - (*this->stream) << "@Method " << inName << "\n"; - ++currentDeep; - if(PrintLineNumber){ - printTab(); - (*this->stream) << "@line " << inLine << "\n"; - } - if(PrintFileName){ - printTab(); - (*this->stream) << "@file " << inFile << "\n"; - } - } - else{ - ++currentDeep; - } - } - return *this; - } - - /** Call this function when leaving a function - * @param inTag the tag at this position - * @param inName the function's name - * <code> - * FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM, __FUNCTION__ ) ); - * </code> - */ - template <class T> - FTrace& leaveFunction(const Tags inTag, const T& inName){ - if(inTag & EnabledTags){ - --currentDeep; - if(currentDeep < MaxDeep){ - printTab(); - (*this->stream) << "@end " << inName << "\n"; - } - } - return *this; - } - - /** Call this function when leaving a function - * @param inTag the tag at this position - * <code> - * FTRACE( FTrace::Controller.leaveFunction(FTrace::FMM) ); - * </code> - */ - FTrace& leaveFunction(const Tags inTag){ - if(inTag & EnabledTags){ - --currentDeep; - if(currentDeep < MaxDeep){ - printTab(); - (*this->stream) << "@end\n"; - } - } - return *this; - } - - /** Call this function when leaving a function - * @param inTag the tag at this position - * @param inName the parameter name - * @param inValue the parameter value - * <code> - * FTRACE( FTrace::Controller.printParameter(FTrace::FMM, "toto" , toto) ); - * </code> - */ - template <class T, class TV> - FTrace& printParameter(const Tags inTag, const T& inName, const TV& inValue){ - if(inTag & EnabledTags){ - if(PrintParameters && currentDeep <= MaxDeep){ - printTab(); - (*this->stream) << "@param " << inName << "\t = " << inValue << ")\n"; - } - } - return *this; - } - - - /** - * To set the debug stream to write into a file - * @param filename the file to write - */ - void writeToFile(const char* const filename){ - close(); - - std::ofstream* const file = new std::ofstream(); - file->open(filename); - - this->stream = file; - } - - /** - * To set the debug stream to write to std::cout - */ - void writeToCout(){ - close(); - this->stream = &std::cout; - } - - /** Flush data into stream */ - void flush(){ - this->stream->flush(); - } - -}; - -#endif //FUSE_TRACE - -#endif //FTRACE_HPP - -// [--LICENSE--] diff --git a/Tests/testApplication.cpp b/Tests/testApplication.cpp index 8ea44c631..c277c6748 100644 --- a/Tests/testApplication.cpp +++ b/Tests/testApplication.cpp @@ -8,17 +8,17 @@ * 3 - Compile as needed */ -#include "../Sources/Utils/FGlobal.hpp" +#include "../Src/Utils/FGlobal.hpp" //================================================================================================ -#ifdef FUSE_MPI -// Compile by mpic++ testApplication.cpp ../Sources/Utils/FAssertable.cpp -o testApplication.exe +#ifdef SCALFMM_USE_MPI +// Compile by mpic++ testApplication.cpp ../Src/Utils/FAssertable.cpp -o testApplication.exe // run by mpirun -np 4 ./testApplication.exe -#include "../Sources/Utils/FMpiApplication.hpp" +#include "../Src/Utils/FMpiApplication.hpp" typedef FMpiApplication ApplicationImplementation; #else -// Compile by g++ testApplication.cpp ../Sources/Utils/FAssertable.cpp -o testApplication.exe -#include "../Sources/Utils/FSingleApplication.hpp" +// Compile by g++ testApplication.cpp ../Src/Utils/FAssertable.cpp -o testApplication.exe +#include "../Src/Utils/FSingleApplication.hpp" typedef FSingleApplication ApplicationImplementation; #endif //================================================================================================ diff --git a/Tests/testAssert.cpp b/Tests/testAssert.cpp index 091041c35..59a08d2fc 100644 --- a/Tests/testAssert.cpp +++ b/Tests/testAssert.cpp @@ -1,7 +1,7 @@ // /!\ Please, you must read the license at the bottom of this page -// Compile by : g++ testAssert.cpp ../Sources/Utils/FAssertable.cpp -o testAssert.exe +// Compile by : g++ testAssert.cpp ../Src/Utils/FAssertable.cpp -o testAssert.exe /** * In this file we show how to use assert and error managing module @@ -11,8 +11,8 @@ #include <iostream> -#include "../Sources/Utils/FSingleApplication.hpp" -#include "../Sources/Utils/FAssertable.hpp" +#include "../Src/Utils/FSingleApplication.hpp" +#include "../Src/Utils/FAssertable.hpp" // This class is a basic application that need to be assertable diff --git a/Tests/testDebug.cpp b/Tests/testDebug.cpp index 41ac3ee45..a02ddb889 100644 --- a/Tests/testDebug.cpp +++ b/Tests/testDebug.cpp @@ -1,12 +1,12 @@ // /!\ Please, you must read the license at the bottom of this page -#include "../Sources/Utils/FDebug.hpp" +#include "../Src/Utils/FDebug.hpp" -// Compile by : g++ testDebug.cpp ../Sources/Utils/FDebug.cpp -o testDebug.exe +// Compile by : g++ testDebug.cpp ../Src/Utils/FDebug.cpp -o testDebug.exe /** * In this file we show how to use the debug module. -* Warning, in FGlobal.hpp (included in FDebug.hpp) FUSE_DEBUG might be undefined. +* Warning, in FGlobal.hpp (included in FDebug.hpp) SCALFMM_USE_DEBUG might be undefined. */ int main(void){ diff --git a/Tests/testFmbAlgorithm.cpp b/Tests/testFmbAlgorithm.cpp index 75fb5ae31..9e933c5f3 100644 --- a/Tests/testFmbAlgorithm.cpp +++ b/Tests/testFmbAlgorithm.cpp @@ -5,31 +5,31 @@ #include <stdio.h> #include <stdlib.h> -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" -#include "../Sources/Containers/FOctree.hpp" -#include "../Sources/Containers/FList.hpp" +#include "../Src/Containers/FOctree.hpp" +#include "../Src/Containers/FList.hpp" -#include "../Sources/Components/FFmaParticle.hpp" -#include "../Sources/Extenssions/FExtendForces.hpp" -#include "../Sources/Extenssions/FExtendPotential.hpp" +#include "../Src/Components/FFmaParticle.hpp" +#include "../Src/Extenssions/FExtendForces.hpp" +#include "../Src/Extenssions/FExtendPotential.hpp" -#include "../Sources/Components/FBasicCell.hpp" -#include "../Sources/Fmb/FExtendFmbCell.hpp" +#include "../Src/Components/FBasicCell.hpp" +#include "../Src/Fmb/FExtendFmbCell.hpp" -#include "../Sources/Core/FFmmAlgorithm.hpp" -#include "../Sources/Core/FFmmAlgorithmThread.hpp" -#include "../Sources/Core/FFmmAlgorithmThreadUs.hpp" +#include "../Src/Core/FFmmAlgorithm.hpp" +#include "../Src/Core/FFmmAlgorithmThread.hpp" +#include "../Src/Core/FFmmAlgorithmThreadUs.hpp" -#include "../Sources/Components/FSimpleLeaf.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" -#include "../Sources/Fmb/FFmbKernels.hpp" +#include "../Src/Fmb/FFmbKernels.hpp" -#include "../Sources/Files/FFmaLoader.hpp" +#include "../Src/Files/FFmaLoader.hpp" -// With openmp : g++ testFmbAlgorithm.cpp ../Sources/Utils/FAssertable.cpp ../Sources/Utils/FDebug.cpp ../Sources/Utils/FTrace.cpp -lgomp -fopenmp -O2 -o testFmbAlgorithm.exe -// icpc -openmp -openmp-lib=compat testFmbAlgorithm.cpp ../Sources/Utils/FAssertable.cpp ../Sources/Utils/FDebug.cpp -O2 -o testFmbAlgorithm.exe +// With openmp : g++ testFmbAlgorithm.cpp ../Src/Utils/FAssertable.cpp ../Src/Utils/FDebug.cpp ../Src/Utils/FTrace.cpp -lgomp -fopenmp -O2 -o testFmbAlgorithm.exe +// icpc -openmp -openmp-lib=compat testFmbAlgorithm.cpp ../Src/Utils/FAssertable.cpp ../Src/Utils/FDebug.cpp -O2 -o testFmbAlgorithm.exe /** This program show an example of use of * the fmm basic algo diff --git a/Tests/testFmbBlasAlgorithm.cpp b/Tests/testFmbBlasAlgorithm.cpp index 12e4b671e..1039744b2 100644 --- a/Tests/testFmbBlasAlgorithm.cpp +++ b/Tests/testFmbBlasAlgorithm.cpp @@ -5,35 +5,35 @@ #include <stdio.h> #include <stdlib.h> -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" -#include "../Sources/Containers/FOctree.hpp" -#include "../Sources/Containers/FList.hpp" +#include "../Src/Containers/FOctree.hpp" +#include "../Src/Containers/FList.hpp" -#include "../Sources/Components/FFmaParticle.hpp" -#include "../Sources/Extenssions/FExtendForces.hpp" -#include "../Sources/Extenssions/FExtendPotential.hpp" +#include "../Src/Components/FFmaParticle.hpp" +#include "../Src/Extenssions/FExtendForces.hpp" +#include "../Src/Extenssions/FExtendPotential.hpp" -#include "../Sources/Components/FBasicCell.hpp" -#include "../Sources/Fmb/FExtendFmbCell.hpp" +#include "../Src/Components/FBasicCell.hpp" +#include "../Src/Fmb/FExtendFmbCell.hpp" -#include "../Sources/Core/FFmmAlgorithm.hpp" -#include "../Sources/Core/FFmmAlgorithmThread.hpp" +#include "../Src/Core/FFmmAlgorithm.hpp" +#include "../Src/Core/FFmmAlgorithmThread.hpp" -#include "../Sources/Components/FSimpleLeaf.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" -#include "../Sources/Fmb/FFmbKernelsBlockBlas.hpp" -#include "../Sources/Fmb/FFmbKernelsBlas.hpp" -#include "../Sources/Fmb/FFmbKernels.hpp" +#include "../Src/Fmb/FFmbKernelsBlockBlas.hpp" +#include "../Src/Fmb/FFmbKernelsBlas.hpp" +#include "../Src/Fmb/FFmbKernels.hpp" -#include "../Sources/Files/FFmaScanfLoader.hpp" +#include "../Src/Files/FFmaScanfLoader.hpp" -// With openmp : g++ testFmbBlasAlgorithm.cpp ../Sources/Utils/FAssertable.cpp ../Sources/Utils/FDebug.cpp ../Sources/Utils/FTrace.cpp -lgomp -fopenmp -lcblas -O2 -o testFmbBlasAlgorithm.exe -// icpc -openmp -openmp-lib=compat testFmbAlgorithm.cpp ../Sources/Utils/FAssertable.cpp ../Sources/Utils/FDebug.cpp -O2 -o testFmbAlgorithm.exe +// With openmp : g++ testFmbBlasAlgorithm.cpp ../Src/Utils/FAssertable.cpp ../Src/Utils/FDebug.cpp ../Src/Utils/FTrace.cpp -lgomp -fopenmp -lcblas -O2 -o testFmbBlasAlgorithm.exe +// icpc -openmp -openmp-lib=compat testFmbAlgorithm.cpp ../Src/Utils/FAssertable.cpp ../Src/Utils/FDebug.cpp -O2 -o testFmbAlgorithm.exe -// icpc -openmp -openmp-lib=compat -lmkl_intel_lp64 -lmkl_sequential -lmkl_core testFmbBlasAlgorithm.cpp ../Sources/Utils/FAssertable.cpp ../Sources/Utils/FDebug.cpp -O2 -o testFmbBlasAlgorithm.exe +// icpc -openmp -openmp-lib=compat -lmkl_intel_lp64 -lmkl_sequential -lmkl_core testFmbBlasAlgorithm.cpp ../Src/Utils/FAssertable.cpp ../Src/Utils/FDebug.cpp -O2 -o testFmbBlasAlgorithm.exe -// g++ testFmbBlasAlgorithm.cpp ../Sources/Utils/FAssertable.cpp ../Sources/Utils/FDebug.cpp ../Sources/Utils/FTrace.cpp -lgomp -fopenmp -lmkl_ia32 -O2 -o testFmbBlasAlgorithm.exe +// g++ testFmbBlasAlgorithm.cpp ../Src/Utils/FAssertable.cpp ../Src/Utils/FDebug.cpp ../Src/Utils/FTrace.cpp -lgomp -fopenmp -lmkl_ia32 -O2 -o testFmbBlasAlgorithm.exe /** This program show an example of use of * the fmm basic algo * it also check that eachh particles is little or longer diff --git a/Tests/testFmbTsmAlgorithm.cpp b/Tests/testFmbTsmAlgorithm.cpp index e218b811a..14b46dbaf 100644 --- a/Tests/testFmbTsmAlgorithm.cpp +++ b/Tests/testFmbTsmAlgorithm.cpp @@ -5,32 +5,32 @@ #include <stdio.h> #include <stdlib.h> -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" -#include "../Sources/Containers/FOctree.hpp" -#include "../Sources/Containers/FList.hpp" +#include "../Src/Containers/FOctree.hpp" +#include "../Src/Containers/FList.hpp" -#include "../Sources/Components/FFmaParticle.hpp" -#include "../Sources/Extenssions/FExtendForces.hpp" -#include "../Sources/Extenssions/FExtendPotential.hpp" +#include "../Src/Components/FFmaParticle.hpp" +#include "../Src/Extenssions/FExtendForces.hpp" +#include "../Src/Extenssions/FExtendPotential.hpp" -#include "../Sources/Extenssions/FExtendParticleType.hpp" +#include "../Src/Extenssions/FExtendParticleType.hpp" -#include "../Sources/Components/FBasicCell.hpp" -#include "../Sources/Fmb/FExtendFmbCell.hpp" +#include "../Src/Components/FBasicCell.hpp" +#include "../Src/Fmb/FExtendFmbCell.hpp" -#include "../Sources/Core/FFmmAlgorithm.hpp" -#include "../Sources/Core/FFmmAlgorithmThread.hpp" +#include "../Src/Core/FFmmAlgorithm.hpp" +#include "../Src/Core/FFmmAlgorithmThread.hpp" -#include "../Sources/Components/FSimpleLeaf.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" -#include "../Sources/Fmb/FFmbKernels.hpp" +#include "../Src/Fmb/FFmbKernels.hpp" -#include "../Sources/Files/FFmaTsmLoader.hpp" +#include "../Src/Files/FFmaTsmLoader.hpp" -// With openmp : g++ testFmbTsmAlgorithm.cpp ../Sources/Utils/FAssertable.cpp ../Sources/Utils/FDebug.cpp ../Sources/Utils/FTrace.cpp -lgomp -fopenmp -O2 -o testFmbTsmAlgorithm.exe -// icpc -openmp -openmp-lib=compat testFmbTsmAlgorithm.cpp ../Sources/Utils/FAssertable.cpp ../Sources/Utils/FDebug.cpp -O2 -o testFmbTsmAlgorithm.exe +// With openmp : g++ testFmbTsmAlgorithm.cpp ../Src/Utils/FAssertable.cpp ../Src/Utils/FDebug.cpp ../Src/Utils/FTrace.cpp -lgomp -fopenmp -O2 -o testFmbTsmAlgorithm.exe +// icpc -openmp -openmp-lib=compat testFmbTsmAlgorithm.cpp ../Src/Utils/FAssertable.cpp ../Src/Utils/FDebug.cpp -O2 -o testFmbTsmAlgorithm.exe /** This program show an example of use of * the fmm basic algo diff --git a/Tests/testFmbTsmNoTsm.cpp b/Tests/testFmbTsmNoTsm.cpp index 950064e47..16dd572f9 100644 --- a/Tests/testFmbTsmNoTsm.cpp +++ b/Tests/testFmbTsmNoTsm.cpp @@ -5,35 +5,35 @@ #include <stdio.h> #include <stdlib.h> -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" -#include "../Sources/Containers/FOctree.hpp" -#include "../Sources/Containers/FList.hpp" +#include "../Src/Containers/FOctree.hpp" +#include "../Src/Containers/FList.hpp" -#include "../Sources/Components/FFmaParticle.hpp" -#include "../Sources/Extenssions/FExtendForces.hpp" -#include "../Sources/Extenssions/FExtendPotential.hpp" +#include "../Src/Components/FFmaParticle.hpp" +#include "../Src/Extenssions/FExtendForces.hpp" +#include "../Src/Extenssions/FExtendPotential.hpp" -#include "../Sources/Extenssions/FExtendParticleType.hpp" -#include "../Sources/Extenssions/FExtendCellType.hpp" +#include "../Src/Extenssions/FExtendParticleType.hpp" +#include "../Src/Extenssions/FExtendCellType.hpp" -#include "../Sources/Components/FBasicCell.hpp" -#include "../Sources/Fmb/FExtendFmbCell.hpp" +#include "../Src/Components/FBasicCell.hpp" +#include "../Src/Fmb/FExtendFmbCell.hpp" -#include "../Sources/Core/FFmmAlgorithm.hpp" -#include "../Sources/Core/FFmmAlgorithmTsm.hpp" -#include "../Sources/Core/FFmmAlgorithmThread.hpp" -#include "../Sources/Core/FFmmAlgorithmThreadTsm.hpp" +#include "../Src/Core/FFmmAlgorithm.hpp" +#include "../Src/Core/FFmmAlgorithmTsm.hpp" +#include "../Src/Core/FFmmAlgorithmThread.hpp" +#include "../Src/Core/FFmmAlgorithmThreadTsm.hpp" -#include "../Sources/Components/FSimpleLeaf.hpp" -#include "../Sources/Components/FTypedLeaf.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" +#include "../Src/Components/FTypedLeaf.hpp" -#include "../Sources/Fmb/FFmbKernels.hpp" +#include "../Src/Fmb/FFmbKernels.hpp" -// With openmp : g++ testFmbTsmAlgorithm.cpp ../Sources/Utils/FAssertable.cpp ../Sources/Utils/FDebug.cpp ../Sources/Utils/FTrace.cpp -lgomp -fopenmp -O2 -o testFmbTsmAlgorithm.exe -// icpc -openmp -openmp-lib=compat testFmbTsmAlgorithm.cpp ../Sources/Utils/FAssertable.cpp ../Sources/Utils/FDebug.cpp -O2 -o testFmbTsmAlgorithm.exe +// With openmp : g++ testFmbTsmAlgorithm.cpp ../Src/Utils/FAssertable.cpp ../Src/Utils/FDebug.cpp ../Src/Utils/FTrace.cpp -lgomp -fopenmp -O2 -o testFmbTsmAlgorithm.exe +// icpc -openmp -openmp-lib=compat testFmbTsmAlgorithm.cpp ../Src/Utils/FAssertable.cpp ../Src/Utils/FDebug.cpp -O2 -o testFmbTsmAlgorithm.exe /** This program show an example of use of * the fmm basic algo diff --git a/Tests/testFmmAlgorithm.cpp b/Tests/testFmmAlgorithm.cpp index 7013bb441..4f5f1b058 100644 --- a/Tests/testFmmAlgorithm.cpp +++ b/Tests/testFmmAlgorithm.cpp @@ -5,26 +5,26 @@ #include <stdio.h> #include <stdlib.h> -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" -#include "../Sources/Containers/FOctree.hpp" -#include "../Sources/Containers/FList.hpp" +#include "../Src/Containers/FOctree.hpp" +#include "../Src/Containers/FList.hpp" -#include "../Sources/Components/FSimpleLeaf.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" -#include "../Sources/Utils/F3DPosition.hpp" +#include "../Src/Utils/F3DPosition.hpp" -#include "../Sources/Components/FTestParticle.hpp" -#include "../Sources/Components/FTestCell.hpp" -#include "../Sources/Components/FTestKernels.hpp" +#include "../Src/Components/FTestParticle.hpp" +#include "../Src/Components/FTestCell.hpp" +#include "../Src/Components/FTestKernels.hpp" -#include "../Sources/Core/FFmmAlgorithm.hpp" -#include "../Sources/Core/FFmmAlgorithmThread.hpp" +#include "../Src/Core/FFmmAlgorithm.hpp" +#include "../Src/Core/FFmmAlgorithmThread.hpp" -#include "../Sources/Components/FBasicKernels.hpp" +#include "../Src/Components/FBasicKernels.hpp" -// Compile by : g++ testFMMAlgorithm.cpp ../Sources/Utils/FAssertable.cpp ../Sources/Utils/FDebug.cpp ../Sources/Utils/FTrace.cpp -lgomp -fopenmp -O2 -o testFMMAlgorithm.exe +// Compile by : g++ testFMMAlgorithm.cpp ../Src/Utils/FAssertable.cpp ../Src/Utils/FDebug.cpp ../Src/Utils/FTrace.cpp -lgomp -fopenmp -O2 -o testFMMAlgorithm.exe /** This program show an example of use of * the fmm basic algo @@ -83,7 +83,7 @@ int main(int argc, char ** argv){ // FTestKernels FBasicKernels FTestKernels<FTestParticle, FTestCell, NbLevels> kernels; //FFmmAlgorithm FFmmAlgorithmThread - FFmmAlgorithmThread<FTestKernels, FTestParticle, FTestCell, FSimpleLeaf, NbLevels, SizeSubLevels> algo(&tree,&kernels); + FFmmAlgorithm<FTestKernels, FTestParticle, FTestCell, FSimpleLeaf, NbLevels, SizeSubLevels> algo(&tree,&kernels); algo.execute(); counter.tac(); diff --git a/Tests/testFmmAlgorithmProc.cpp b/Tests/testFmmAlgorithmProc.cpp index 31d44a8b4..93915a1b9 100644 --- a/Tests/testFmmAlgorithmProc.cpp +++ b/Tests/testFmmAlgorithmProc.cpp @@ -5,25 +5,28 @@ #include <stdio.h> #include <stdlib.h> -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" -#include "../Sources/Containers/FOctree.hpp" -#include "../Sources/Containers/FList.hpp" +#include "../Src/Containers/FOctree.hpp" +#include "../Src/Containers/FList.hpp" -#include "../Sources/Components/FSimpleLeaf.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" -#include "../Sources/Utils/F3DPosition.hpp" +#include "../Src/Utils/F3DPosition.hpp" -#include "../Sources/Components/FTestParticle.hpp" -#include "../Sources/Components/FTestCell.hpp" -#include "../Sources/Components/FTestKernels.hpp" +#include "../Src/Components/FFmaParticle.hpp" +#include "../Src/Components/FTestParticle.hpp" +#include "../Src/Components/FTestCell.hpp" +#include "../Src/Components/FTestKernels.hpp" +#include "../Src/Extenssions/FExtendPhysicalValue.hpp" -#include "../Sources/Core/FFmmAlgorithmThreadProc.hpp" +#include "../Src/Core/FFmmAlgorithmThreadProc.hpp" +#include "../Src/Files/FFmaLoader.hpp" -#include "../Sources/Components/FBasicKernels.hpp" +#include "../Src/Components/FBasicKernels.hpp" -// Compile by : g++ testFmmAlgorithmProc.cpp ../Sources/Utils/FAssertable.cpp ../Sources/Utils/FDebug.cpp ../Sources/Utils/FTrace.cpp -lgomp -fopenmp -O2 -o testFmmAlgorithmProc.exe +// Compile by : g++ testFmmAlgorithmProc.cpp ../Src/Utils/FAssertable.cpp ../Src/Utils/FDebug.cpp ../Src/Utils/FTrace.cpp -lgomp -fopenmp -O2 -o testFmmAlgorithmProc.exe /** This program show an example of use of * the fmm basic algo @@ -31,6 +34,22 @@ */ +/** Fmb class has to extend {FExtendForces,FExtendPotential,FExtendPhysicalValue} + * Because we use fma loader it needs {FFmaParticle} + */ +class TestParticle : public FTestParticle, public FExtendPhysicalValue { +public: +}; + +class FTestCellPar : public FTestCell{ +public : + void addCell(const FTestCellPar& other){ + setDataUp(this->getDataUp() + other.getDataUp()); + setDataDown(this->getDataDown() + other.getDataDown()); + } +}; + + // Simply create particles and try the kernels int main(int argc, char ** argv){ ///////////////////////What we do///////////////////////////// @@ -39,21 +58,37 @@ int main(int argc, char ** argv){ const int NbLevels = 10;//10; const int SizeSubLevels = 3;//3 - const long NbPart = 20000;//2000000 - FTestParticle* particles = new FTestParticle[NbPart]; + const char* const defaultFilename = "testLoaderFMA.fma"; //../../Data/ "testLoaderFMA.fma" "testFMAlgorithm.fma" Sphere.fma + const char* filename; FTic counter; + if(argc == 1){ + std::cout << "You have to give a .fma file in argument.\n"; + std::cout << "The program will try a default file : " << defaultFilename << "\n"; + filename = defaultFilename; + } + else{ + filename = argv[1]; + std::cout << "Opening : " << filename << "\n"; + } - srand ( 1 ); // volontary set seed to constant + FFmaLoader<TestParticle> loader(filename); + if(!loader.isValide()){ + std::cout << "Loader Error, " << filename << " is missing\n"; + return 1; + } ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// - std::cout << "Creating " << NbPart << " particles ..." << std::endl; + std::cout << "Creating " << loader.getNumberOfParticles() << " particles ..." << std::endl; counter.tic(); - for(long idxPart = 0 ; idxPart < NbPart ; ++idxPart){ - particles[idxPart].setPosition(FReal(rand())/RAND_MAX,FReal(rand())/RAND_MAX,FReal(rand())/RAND_MAX); + + TestParticle* particles = new TestParticle[loader.getNumberOfParticles()]; + + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particles[idxPart]); } counter.tac(); @@ -62,14 +97,14 @@ int main(int argc, char ** argv){ ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// - FOctree<FTestParticle, FTestCell, FSimpleLeaf, NbLevels, SizeSubLevels> tree(1.0,F3DPosition(0.5,0.5,0.5)); + FOctree<TestParticle, FTestCellPar, FSimpleLeaf, NbLevels, SizeSubLevels> tree(loader.getBoxWidth(),loader.getCenterOfBox()); ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// std::cout << "Inserting particles ..." << std::endl; counter.tic(); - for(long idxPart = 0 ; idxPart < NbPart ; ++idxPart){ + for(long idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ tree.insert(&particles[idxPart]); } counter.tac(); @@ -82,9 +117,9 @@ int main(int argc, char ** argv){ counter.tic(); // FTestKernels FBasicKernels - FTestKernels<FTestParticle, FTestCell, NbLevels> kernels; + FTestKernels<TestParticle, FTestCellPar, NbLevels> kernels; //FFmmAlgorithm FFmmAlgorithmThreaded FFmmAlgorithmThreadProc - FFmmAlgorithmThreadProc<FTestKernels, FTestParticle, FTestCell, FSimpleLeaf, NbLevels, SizeSubLevels> algo(&tree,&kernels,argc,argv); + FFmmAlgorithmThreadProc<FTestKernels, TestParticle, FTestCellPar, FSimpleLeaf, NbLevels, SizeSubLevels> algo(&tree,&kernels,argc,argv); algo.execute(); counter.tac(); diff --git a/Tests/testFmmAlgorithmTsm.cpp b/Tests/testFmmAlgorithmTsm.cpp index 13b7e30bd..4da57b8e7 100644 --- a/Tests/testFmmAlgorithmTsm.cpp +++ b/Tests/testFmmAlgorithmTsm.cpp @@ -5,26 +5,26 @@ #include <stdio.h> #include <stdlib.h> -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" -#include "../Sources/Containers/FOctree.hpp" -#include "../Sources/Containers/FList.hpp" +#include "../Src/Containers/FOctree.hpp" +#include "../Src/Containers/FList.hpp" -#include "../Sources/Components/FTypedLeaf.hpp" +#include "../Src/Components/FTypedLeaf.hpp" -#include "../Sources/Utils/F3DPosition.hpp" +#include "../Src/Utils/F3DPosition.hpp" -#include "../Sources/Components/FTestParticle.hpp" -#include "../Sources/Components/FTestCell.hpp" -#include "../Sources/Components/FTestKernels.hpp" +#include "../Src/Components/FTestParticle.hpp" +#include "../Src/Components/FTestCell.hpp" +#include "../Src/Components/FTestKernels.hpp" -#include "../Sources/Extenssions/FExtendParticleType.hpp" -#include "../Sources/Extenssions/FExtendCellType.hpp" +#include "../Src/Extenssions/FExtendParticleType.hpp" +#include "../Src/Extenssions/FExtendCellType.hpp" -#include "../Sources/Core/FFmmAlgorithmTsm.hpp" -#include "../Sources/Core/FFmmAlgorithmThreadTsm.hpp" +#include "../Src/Core/FFmmAlgorithmTsm.hpp" +#include "../Src/Core/FFmmAlgorithmThreadTsm.hpp" -#include "../Sources/Components/FBasicKernels.hpp" +#include "../Src/Components/FBasicKernels.hpp" /** This program show an example of use of * the fmm basic algo diff --git a/Tests/testLoader.cpp b/Tests/testLoader.cpp index 3fa251939..d12580e6f 100644 --- a/Tests/testLoader.cpp +++ b/Tests/testLoader.cpp @@ -6,22 +6,22 @@ #include <stdlib.h> #include <time.h> -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" -#include "../Sources/Containers/FOctree.hpp" -#include "../Sources/Containers/FList.hpp" +#include "../Src/Containers/FOctree.hpp" +#include "../Src/Containers/FList.hpp" -#include "../Sources/Utils/FAssertable.hpp" -#include "../Sources/Utils/F3DPosition.hpp" +#include "../Src/Utils/FAssertable.hpp" +#include "../Src/Utils/F3DPosition.hpp" -#include "../Sources/Components/FBasicParticle.hpp" -#include "../Sources/Components/FBasicCell.hpp" +#include "../Src/Components/FBasicParticle.hpp" +#include "../Src/Components/FBasicCell.hpp" -#include "../Sources/Components/FSimpleLeaf.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" -#include "../Sources/Files/FBasicLoader.hpp" +#include "../Src/Files/FBasicLoader.hpp" -// Compile by : g++ testLoader.cpp ../Sources/Utils/FAssertable.cpp -O2 -o testLoader.exe +// Compile by : g++ testLoader.cpp ../Src/Utils/FAssertable.cpp -O2 -o testLoader.exe /** diff --git a/Tests/testLoaderCreate.cpp b/Tests/testLoaderCreate.cpp index 5d62a16d3..8b84ba926 100644 --- a/Tests/testLoaderCreate.cpp +++ b/Tests/testLoaderCreate.cpp @@ -7,7 +7,7 @@ #include <stdlib.h> #include <time.h> -#include "../Sources/Utils/FGlobal.hpp" +#include "../Src/Utils/FGlobal.hpp" // This file can generate basic particles files to load with basic loader // g++ testLoaderCreate.cpp -o testLoaderCreate.exe diff --git a/Tests/testLoaderFMA.cpp b/Tests/testLoaderFMA.cpp index f86bd0dfb..79a9fa9e1 100644 --- a/Tests/testLoaderFMA.cpp +++ b/Tests/testLoaderFMA.cpp @@ -6,22 +6,22 @@ #include <stdlib.h> #include <time.h> -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" -#include "../Sources/Containers/FOctree.hpp" -#include "../Sources/Containers/FList.hpp" +#include "../Src/Containers/FOctree.hpp" +#include "../Src/Containers/FList.hpp" -#include "../Sources/Utils/FAssertable.hpp" -#include "../Sources/Utils/F3DPosition.hpp" +#include "../Src/Utils/FAssertable.hpp" +#include "../Src/Utils/F3DPosition.hpp" -#include "../Sources/Components/FFmaParticle.hpp" -#include "../Sources/Components/FBasicCell.hpp" +#include "../Src/Components/FFmaParticle.hpp" +#include "../Src/Components/FBasicCell.hpp" -#include "../Sources/Components/FSimpleLeaf.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" -#include "../Sources/Files/FFmaLoader.hpp" +#include "../Src/Files/FFmaLoader.hpp" -// Compile by : g++ testLoaderFMA.cpp ../Sources/Utils/FAssertable.cpp -O2 -o testLoaderFMA.exe +// Compile by : g++ testLoaderFMA.cpp ../Src/Utils/FAssertable.cpp -O2 -o testLoaderFMA.exe /** diff --git a/Tests/testLoaderFMACreate.cpp b/Tests/testLoaderFMACreate.cpp index cb0a6c8cd..9c72b3710 100644 --- a/Tests/testLoaderFMACreate.cpp +++ b/Tests/testLoaderFMACreate.cpp @@ -7,7 +7,7 @@ #include <stdlib.h> #include <time.h> -#include "../Sources/Utils/FGlobal.hpp" +#include "../Src/Utils/FGlobal.hpp" // This file can generate basic particles files in the FMA format // g++ testLoaderFMACreate.cpp -o testLoaderFMACreate.exe diff --git a/Tests/testLoaderFMACreateSphere.cpp b/Tests/testLoaderFMACreateSphere.cpp index fe0f875fe..76ef63365 100644 --- a/Tests/testLoaderFMACreateSphere.cpp +++ b/Tests/testLoaderFMACreateSphere.cpp @@ -9,7 +9,7 @@ #include <cmath> -#include "../Sources/Utils/FGlobal.hpp" +#include "../Src/Utils/FGlobal.hpp" // This file can generate basic particles files to load with basic loader // g++ testLoaderCreateSphere.cpp -O2 -o testLoaderCreateSphere.exe diff --git a/Tests/testLoaderFMATsm.cpp b/Tests/testLoaderFMATsm.cpp index 6c2a0b839..9c2399495 100644 --- a/Tests/testLoaderFMATsm.cpp +++ b/Tests/testLoaderFMATsm.cpp @@ -6,24 +6,24 @@ #include <stdlib.h> #include <time.h> -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" -#include "../Sources/Containers/FOctree.hpp" -#include "../Sources/Containers/FList.hpp" +#include "../Src/Containers/FOctree.hpp" +#include "../Src/Containers/FList.hpp" -#include "../Sources/Utils/FAssertable.hpp" -#include "../Sources/Utils/F3DPosition.hpp" +#include "../Src/Utils/FAssertable.hpp" +#include "../Src/Utils/F3DPosition.hpp" -#include "../Sources/Components/FFmaParticle.hpp" -#include "../Sources/Components/FBasicCell.hpp" +#include "../Src/Components/FFmaParticle.hpp" +#include "../Src/Components/FBasicCell.hpp" -#include "../Sources/Extenssions/FExtendParticleType.hpp" +#include "../Src/Extenssions/FExtendParticleType.hpp" -#include "../Sources/Components/FSimpleLeaf.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" -#include "../Sources/Files/FFmaTsmLoader.hpp" +#include "../Src/Files/FFmaTsmLoader.hpp" -// Compile by : g++ testLoaderFMATsm.cpp ../Sources/Utils/FAssertable.cpp -O2 -o testLoaderFMATsm.exe +// Compile by : g++ testLoaderFMATsm.cpp ../Src/Utils/FAssertable.cpp -O2 -o testLoaderFMATsm.exe class ParticleTsm : public FFmaParticle, public FExtendParticleType { diff --git a/Tests/testLoaderFMATsmCreate.cpp b/Tests/testLoaderFMATsmCreate.cpp index c40779a29..769c0ba92 100644 --- a/Tests/testLoaderFMATsmCreate.cpp +++ b/Tests/testLoaderFMATsmCreate.cpp @@ -7,7 +7,7 @@ #include <stdlib.h> #include <time.h> -#include "../Sources/Utils/FGlobal.hpp" +#include "../Src/Utils/FGlobal.hpp" // This file can generate basic particles files in the FMA format // g++ testLoaderFMATsmCreate.cpp -o testLoaderFMATsmCreate.exe diff --git a/Tests/testOctree.cpp b/Tests/testOctree.cpp index 155a0f09e..79787801b 100644 --- a/Tests/testOctree.cpp +++ b/Tests/testOctree.cpp @@ -6,19 +6,19 @@ #include <stdlib.h> #include <time.h> -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" -#include "../Sources/Containers/FOctree.hpp" -#include "../Sources/Containers/FList.hpp" +#include "../Src/Containers/FOctree.hpp" +#include "../Src/Containers/FList.hpp" -#include "../Sources/Utils/FAssertable.hpp" -#include "../Sources/Utils/F3DPosition.hpp" +#include "../Src/Utils/FAssertable.hpp" +#include "../Src/Utils/F3DPosition.hpp" -#include "../Sources/Components/FBasicParticle.hpp" -#include "../Sources/Components/FBasicCell.hpp" -#include "../Sources/Components/FSimpleLeaf.hpp" +#include "../Src/Components/FBasicParticle.hpp" +#include "../Src/Components/FBasicCell.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" -// Compile by : g++ testOctree.cpp ../Sources/Utils/FAssertable.cpp -O2 -o testOctree.exe +// Compile by : g++ testOctree.cpp ../Src/Utils/FAssertable.cpp -O2 -o testOctree.exe /** * In this file we show how to use octree diff --git a/Tests/testOctreeIter.cpp b/Tests/testOctreeIter.cpp index ca6468ee3..1ced7dc07 100644 --- a/Tests/testOctreeIter.cpp +++ b/Tests/testOctreeIter.cpp @@ -7,19 +7,19 @@ #include <time.h> -#include "../Sources/Containers/FOctree.hpp" -#include "../Sources/Containers/FList.hpp" -#include "../Sources/Components/FSimpleLeaf.hpp" +#include "../Src/Containers/FOctree.hpp" +#include "../Src/Containers/FList.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" -#include "../Sources/Utils/FAssertable.hpp" -#include "../Sources/Utils/F3DPosition.hpp" +#include "../Src/Utils/FAssertable.hpp" +#include "../Src/Utils/F3DPosition.hpp" -#include "../Sources/Components/FBasicParticle.hpp" -#include "../Sources/Components/FBasicCell.hpp" +#include "../Src/Components/FBasicParticle.hpp" +#include "../Src/Components/FBasicCell.hpp" -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" -// Compile by : g++ testOctreeIter.cpp ../Sources/Utils/FAssertable.cpp -O2 -o testOctreeIter.exe +// Compile by : g++ testOctreeIter.cpp ../Src/Utils/FAssertable.cpp -O2 -o testOctreeIter.exe /** * In this file we show how to use octree with iteration diff --git a/Tests/testOctreePrintMorton.cpp b/Tests/testOctreePrintMorton.cpp index 04aa82439..135cfb980 100644 --- a/Tests/testOctreePrintMorton.cpp +++ b/Tests/testOctreePrintMorton.cpp @@ -7,9 +7,9 @@ #include <time.h> #include <string> -#include "../Sources/Containers/FTreeCoordinate.hpp" -#include "../Sources/Utils/F3DPosition.hpp" -#include "../Sources/Utils/FMath.hpp" +#include "../Src/Containers/FTreeCoordinate.hpp" +#include "../Src/Utils/F3DPosition.hpp" +#include "../Src/Utils/FMath.hpp" // Compile by : g++ testOctreePrintMorton.cpp -O2 -o testOctreePrintMorton.exe diff --git a/Tests/testTic.cpp b/Tests/testTic.cpp index 0a32383b7..872876b0a 100644 --- a/Tests/testTic.cpp +++ b/Tests/testTic.cpp @@ -1,5 +1,5 @@ #include <iostream> -#include "../Sources/Utils/FTic.hpp" +#include "../Src/Utils/FTic.hpp" #include <stdlib.h> #include <unistd.h> diff --git a/UTests/utestConvert.cpp b/UTests/utestConvert.cpp index b0d56a85a..843e04860 100644 --- a/UTests/utestConvert.cpp +++ b/UTests/utestConvert.cpp @@ -1,10 +1,10 @@ #include "FUTester.hpp" -#include "../Sources/Utils/FGlobal.hpp" -#include "../Sources/Utils/F3DPosition.hpp" -#include "../Sources/Containers/FTreeCoordinate.hpp" -#include "../Sources/Utils/FConvert.hpp" -#include "../Sources/Utils/FMath.hpp" +#include "../Src/Utils/FGlobal.hpp" +#include "../Src/Utils/F3DPosition.hpp" +#include "../Src/Containers/FTreeCoordinate.hpp" +#include "../Src/Utils/FConvert.hpp" +#include "../Src/Utils/FMath.hpp" // compile by g++ utestConvert.cpp -o utestConvert.exe diff --git a/UTests/utestList.cpp b/UTests/utestList.cpp index 0a1c2954f..8534e9d3c 100644 --- a/UTests/utestList.cpp +++ b/UTests/utestList.cpp @@ -1,104 +1,104 @@ -#include "FUTester.hpp" - -#include "../Sources/Containers/FList.hpp" - -// compile by g++ utestList.cpp -o utestList.exe - -/** -* This file is a unit test for the FList class -*/ - -/** -* This class is simply used to count alloc dealloc -*/ -class TestObject{ -public: - static int counter; - static int dealloced; - - TestObject(){ - ++counter; - } - TestObject(const TestObject&){ - ++counter; - } - ~TestObject(){ - ++dealloced; - } -}; - -int TestObject::counter(0); -int TestObject::dealloced(0); - - -/** this class test the list container */ -class TestList : public FUTester<TestList> { - // Called before each test : simply set counter to 0 - void PreTest(){ - TestObject::counter = 0; - TestObject::dealloced = 0; - } - - // test size - void TestSize(){ - FList<TestObject> list; - list.pushFront(TestObject()); - list.pushFront(TestObject()); - list.pushFront(TestObject()); - assert(list.getSize() == 3); - - assert((TestObject::counter - TestObject::dealloced) == list.getSize()); - - list.clear(); - assert(list.getSize() == 0); - - assert(TestObject::counter == TestObject::dealloced); - } - - // test copy - void TestCopy(){ - FList<TestObject> list; - list.pushFront(TestObject()); - list.pushFront(TestObject()); - list.pushFront(TestObject()); - - FList<TestObject> list2 = list; - assert(list.getSize() == list2.getSize()); - - assert((TestObject::counter - TestObject::dealloced) == (list.getSize() + list2.getSize())); - } - - // test iter - void TestIter(){ - FList<TestObject> list; - { - FList<TestObject>::BasicIterator iter(list); - assert(!iter.isValide()); - } - { - list.pushFront(TestObject()); - list.pushFront(TestObject()); - list.pushFront(TestObject()); - - FList<TestObject>::BasicIterator iter(list); - assert(iter.isValide()); - - int counter = 0; - while(iter.isValide()){ iter.progress(); ++counter; } - assert(!iter.isValide()); - assert(counter == list.getSize()); - } - } - - // set test - void SetTests(){ - AddTest(&TestList::TestSize,"Test Size"); - AddTest(&TestList::TestCopy,"Test Copy"); - AddTest(&TestList::TestIter,"Test Iter"); - } -}; - -// You must do this -TestClass(TestList) - - +#include "FUTester.hpp" + +#include "../Src/Containers/FList.hpp" + +// compile by g++ utestList.cpp -o utestList.exe + +/** +* This file is a unit test for the FList class +*/ + +/** +* This class is simply used to count alloc dealloc +*/ +class TestObject{ +public: + static int counter; + static int dealloced; + + TestObject(){ + ++counter; + } + TestObject(const TestObject&){ + ++counter; + } + ~TestObject(){ + ++dealloced; + } +}; + +int TestObject::counter(0); +int TestObject::dealloced(0); + + +/** this class test the list container */ +class TestList : public FUTester<TestList> { + // Called before each test : simply set counter to 0 + void PreTest(){ + TestObject::counter = 0; + TestObject::dealloced = 0; + } + + // test size + void TestSize(){ + FList<TestObject> list; + list.pushFront(TestObject()); + list.pushFront(TestObject()); + list.pushFront(TestObject()); + assert(list.getSize() == 3); + + assert((TestObject::counter - TestObject::dealloced) == list.getSize()); + + list.clear(); + assert(list.getSize() == 0); + + assert(TestObject::counter == TestObject::dealloced); + } + + // test copy + void TestCopy(){ + FList<TestObject> list; + list.pushFront(TestObject()); + list.pushFront(TestObject()); + list.pushFront(TestObject()); + + FList<TestObject> list2 = list; + assert(list.getSize() == list2.getSize()); + + assert((TestObject::counter - TestObject::dealloced) == (list.getSize() + list2.getSize())); + } + + // test iter + void TestIter(){ + FList<TestObject> list; + { + FList<TestObject>::BasicIterator iter(list); + assert(!iter.isValide()); + } + { + list.pushFront(TestObject()); + list.pushFront(TestObject()); + list.pushFront(TestObject()); + + FList<TestObject>::BasicIterator iter(list); + assert(iter.isValide()); + + int counter = 0; + while(iter.isValide()){ iter.progress(); ++counter; } + assert(!iter.isValide()); + assert(counter == list.getSize()); + } + } + + // set test + void SetTests(){ + AddTest(&TestList::TestSize,"Test Size"); + AddTest(&TestList::TestCopy,"Test Copy"); + AddTest(&TestList::TestIter,"Test Iter"); + } +}; + +// You must do this +TestClass(TestList) + + diff --git a/UTests/utestMorton.cpp b/UTests/utestMorton.cpp index 91ff20b8c..7381d8458 100644 --- a/UTests/utestMorton.cpp +++ b/UTests/utestMorton.cpp @@ -1,71 +1,71 @@ -#include "FUTester.hpp" - -#include "../Sources/Containers/FTreeCoordinate.hpp" - -// compile by g++ utestMorton.cpp -o utestMorton.exe - -/** -* This file is a unit test for the FTreeCoordinate class -*/ - - -/** this class test the list container */ -class TestMorton : public FUTester<TestMorton> { - void Morton(){ - { - FTreeCoordinate pos(5,1,7); - FTreeCoordinate cp; - cp.setPositionFromMorton(pos.getMortonIndex(10),10); - assert(pos == cp); - assert(cp.getMortonIndex(10) == pos.getMortonIndex(10)); - } - { - FTreeCoordinate pos(2,8,3); - FTreeCoordinate cp; - cp.setPositionFromMorton(pos.getMortonIndex(10),10); - assert(pos == cp); - assert(cp.getMortonIndex(10) == pos.getMortonIndex(10)); - } - { - FTreeCoordinate pos(51,11,47); - FTreeCoordinate cp; - cp.setPositionFromMorton(pos.getMortonIndex(10),10); - assert(pos == cp); - assert(cp.getMortonIndex(10) == pos.getMortonIndex(10)); - } - } - - void Position(){ - { - FTreeCoordinate pos(0,0,0); - assert(pos.getMortonIndex(1) == 0); - } - { - FTreeCoordinate pos(1,1,1); - assert(pos.getMortonIndex(1) == 7); - } - { - FTreeCoordinate pos(0,1,1); - assert(pos.getMortonIndex(1) == 3); - } - { - FTreeCoordinate pos(2,2,2); - assert(pos.getMortonIndex(2) == (7 << 3) ); - } - { - FTreeCoordinate pos(1,2,4); - assert(pos.getMortonIndex(3) == 84 );// 001 010 100 =>> 001010100 => 84d - } - } - - // set test - void SetTests(){ - AddTest(&TestMorton::Morton,"Test Morton"); - AddTest(&TestMorton::Position,"Test Position"); - } -}; - -// You must do this -TestClass(TestMorton) - - +#include "FUTester.hpp" + +#include "../Src/Containers/FTreeCoordinate.hpp" + +// compile by g++ utestMorton.cpp -o utestMorton.exe + +/** +* This file is a unit test for the FTreeCoordinate class +*/ + + +/** this class test the list container */ +class TestMorton : public FUTester<TestMorton> { + void Morton(){ + { + FTreeCoordinate pos(5,1,7); + FTreeCoordinate cp; + cp.setPositionFromMorton(pos.getMortonIndex(10),10); + assert(pos == cp); + assert(cp.getMortonIndex(10) == pos.getMortonIndex(10)); + } + { + FTreeCoordinate pos(2,8,3); + FTreeCoordinate cp; + cp.setPositionFromMorton(pos.getMortonIndex(10),10); + assert(pos == cp); + assert(cp.getMortonIndex(10) == pos.getMortonIndex(10)); + } + { + FTreeCoordinate pos(51,11,47); + FTreeCoordinate cp; + cp.setPositionFromMorton(pos.getMortonIndex(10),10); + assert(pos == cp); + assert(cp.getMortonIndex(10) == pos.getMortonIndex(10)); + } + } + + void Position(){ + { + FTreeCoordinate pos(0,0,0); + assert(pos.getMortonIndex(1) == 0); + } + { + FTreeCoordinate pos(1,1,1); + assert(pos.getMortonIndex(1) == 7); + } + { + FTreeCoordinate pos(0,1,1); + assert(pos.getMortonIndex(1) == 3); + } + { + FTreeCoordinate pos(2,2,2); + assert(pos.getMortonIndex(2) == (7 << 3) ); + } + { + FTreeCoordinate pos(1,2,4); + assert(pos.getMortonIndex(3) == 84 );// 001 010 100 =>> 001010100 => 84d + } + } + + // set test + void SetTests(){ + AddTest(&TestMorton::Morton,"Test Morton"); + AddTest(&TestMorton::Position,"Test Position"); + } +}; + +// You must do this +TestClass(TestMorton) + + -- GitLab