From d940c321ea21d2591aa9dd08cc26b84594ff96f7 Mon Sep 17 00:00:00 2001 From: bramas <berenger.bramas@inria.fr> Date: Thu, 6 Jun 2013 12:30:47 +0200 Subject: [PATCH] Major update to move to new leaf a smaller revision will come after test and comments --- Src/Arranger/FOctreeArranger.hpp | 38 +- Src/Components/FAbstractLeaf.hpp | 10 +- ...cle.hpp => FAbstractParticleContainer.hpp} | 29 +- Src/Components/FBasicCell.hpp | 1 - Src/Components/FBasicParticleContainer.hpp | 204 ++++++++ ...Particle.hpp => FFmaParticleContainer.hpp} | 29 +- Src/Components/FSimpleLeaf.hpp | 9 +- Src/Components/FTestKernels.hpp | 44 +- Src/Components/FTestParticle.hpp | 73 --- ...article.hpp => FTestParticleContainer.hpp} | 35 +- Src/Components/FTypedLeaf.hpp | 13 +- Src/Containers/FOctree.hpp | 65 ++- Src/Containers/FSubOctree.hpp | 127 +++-- Src/Containers/FTreeCoordinate.hpp | 22 + Src/Core/FFmmAlgorithm.hpp | 2 +- Src/Core/FFmmAlgorithmPeriodic.hpp | 33 +- Src/Core/FFmmAlgorithmSectionTask.hpp | 2 +- Src/Core/FFmmAlgorithmTask.hpp | 2 +- Src/Core/FFmmAlgorithmThread.hpp | 2 +- Src/Core/FFmmAlgorithmThreadProc.hpp | 2 +- Src/Core/FFmmAlgorithmThreadTsm.hpp | 6 +- Src/Core/FFmmAlgorithmTsm.hpp | 6 +- Src/Extensions/FExtendForces.hpp | 87 ---- Src/Extensions/FExtendParticleType.hpp | 105 ---- Src/Extensions/FExtendPhysicalValue.hpp | 74 --- Src/Extensions/FExtendPosition.hpp | 93 ---- Src/Extensions/FExtendPotential.hpp | 78 --- Src/Extensions/FExtendVelocity.hpp | 88 ---- Src/Files/FAbstractLoader.hpp | 21 +- Src/Files/FBasicLoader.hpp | 7 +- Src/Files/FEwalLoader.hpp | 94 +--- Src/Files/FFmaBinLoader.hpp | 9 +- Src/Files/FFmaLoader.hpp | 9 +- Src/Files/FFmaScanfLoader.hpp | 9 +- Src/Files/FFmaTsmLoader.hpp | 13 +- Src/Files/FHLoader.hpp | 9 +- Src/Files/FMpiFmaLoader.hpp | 9 +- Src/Files/FRandomLoader.hpp | 20 +- Src/Files/FTreeCsvSaver.hpp | 33 +- Src/Files/FTreeIO.hpp | 58 +-- Src/Kernels/Chebyshev/FAbstractChebKernel.hpp | 176 +------ Src/Kernels/Chebyshev/FChebFlopsSymKernel.hpp | 30 +- Src/Kernels/Chebyshev/FChebInterpolator.hpp | 110 ++-- Src/Kernels/Chebyshev/FChebKernel.hpp | 9 +- Src/Kernels/Chebyshev/FChebParticle.hpp | 45 -- Src/Kernels/Chebyshev/FChebSymKernel.hpp | 7 +- Src/Kernels/P2P/FP2P.hpp | 469 ++++++++++++++++++ Src/Kernels/P2P/FP2PParticleContainer.hpp | 66 +++ .../P2P/FP2PParticleContainerIndexed.hpp | 25 + Src/Kernels/Rotation/FRotationKernel.hpp | 173 ++----- .../Rotation/FRotationOriginalKernel.hpp | 153 ++---- Src/Kernels/Rotation/FRotationParticle.hpp | 58 --- .../Rotation/FRotationParticleContainer.hpp | 66 +++ .../Spherical/FAbstractSphericalKernel.hpp | 281 +++-------- .../Spherical/FSphericalBlasKernel.hpp | 6 +- .../Spherical/FSphericalBlockBlasKernel.hpp | 6 +- Src/Kernels/Spherical/FSphericalKernel.hpp | 6 +- Src/Kernels/Spherical/FSphericalParticle.hpp | 58 --- .../Spherical/FSphericalRotationKernel.hpp | 6 +- Tests/Kernels/testChebAlgorithm.cpp | 34 +- Tests/Kernels/testCompareKernels.cpp | 309 +++--------- Tests/Kernels/testFlopsChebAlgorithm.cpp | 35 +- Tests/Kernels/testRotationAlgorithm.cpp | 54 +- Tests/Kernels/testSphericalAlgorithm.cpp | 55 +- Tests/Kernels/testSphericalBench.cpp | 149 +++--- Tests/Kernels/testSphericalBlasAlgorithm.cpp | 55 +- .../testSphericalBlockBlasAlgorithm.cpp | 56 ++- Tests/Kernels/testSphericalEwalAlgorithm.cpp | 181 ++++--- Tests/Kernels/testSphericalGalaxyCsv.cpp | 126 +++-- .../testSphericalRotationAlgorithm.cpp | 55 +- Tests/Kernels/testSphericalTsmAlgorithm.cpp | 52 +- Tests/Kernels/testSphericalTsmNoTsm.cpp | 200 -------- Tests/Kernels/testTuneSphericalBlockBlas.cpp | 25 +- Tests/Utils/testChebInterpolator.cpp | 62 ++- Tests/Utils/testChebOctree.cpp | 40 +- Tests/Utils/testChebSxUCBSy.cpp | 67 +-- Tests/Utils/testCompareIOTree.cpp | 21 +- Tests/Utils/testFmmAlgorithm.cpp | 25 +- Tests/Utils/testFmmAlgorithmPeriodic.cpp | 56 +-- Tests/Utils/testFmmAlgorithmProc.cpp | 2 +- Tests/Utils/testFmmAlgorithmTsm.cpp | 34 +- Tests/Utils/testFmmDemonstration.cpp | 112 +++-- Tests/Utils/testLoader.cpp | 17 +- Tests/Utils/testLoaderFMA.cpp | 18 +- Tests/Utils/testLoaderFMATsm.cpp | 29 +- Tests/Utils/testMemStats.cpp | 26 +- Tests/Utils/testMortonIndex.cpp | 194 -------- Tests/Utils/testOctree.cpp | 16 +- Tests/Utils/testOctreeFuncteur.cpp | 25 +- Tests/Utils/testOctreeIter.cpp | 14 +- Tests/Utils/testOctreeRearrange.cpp | 93 +++- Tests/Utils/testStatsTree.cpp | 26 +- Tests/Utils/testTreeIO.cpp | 23 +- UTests/utestChebyshevDirect.cpp | 159 +++--- UTests/utestChebyshevDirectPeriodic.cpp | 153 +++--- UTests/utestOctree.cpp | 14 +- UTests/utestRotationDirect.cpp | 107 ++-- UTests/utestRotationDirectPeriodic.cpp | 128 +++-- UTests/utestSphericalDirect.cpp | 140 +++--- UTests/utestSphericalDirectPeriodic.cpp | 121 ++--- UTests/utestSphericalWithPrevious.cpp | 48 +- 101 files changed, 2869 insertions(+), 3607 deletions(-) rename Src/Components/{FAbstractParticle.hpp => FAbstractParticleContainer.hpp} (73%) create mode 100755 Src/Components/FBasicParticleContainer.hpp rename Src/Components/{FFmaParticle.hpp => FFmaParticleContainer.hpp} (60%) delete mode 100755 Src/Components/FTestParticle.hpp rename Src/Components/{FBasicParticle.hpp => FTestParticleContainer.hpp} (57%) delete mode 100755 Src/Extensions/FExtendForces.hpp delete mode 100755 Src/Extensions/FExtendParticleType.hpp delete mode 100755 Src/Extensions/FExtendPhysicalValue.hpp delete mode 100755 Src/Extensions/FExtendPosition.hpp delete mode 100755 Src/Extensions/FExtendPotential.hpp delete mode 100755 Src/Extensions/FExtendVelocity.hpp delete mode 100755 Src/Kernels/Chebyshev/FChebParticle.hpp create mode 100644 Src/Kernels/P2P/FP2P.hpp create mode 100644 Src/Kernels/P2P/FP2PParticleContainer.hpp create mode 100644 Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp delete mode 100755 Src/Kernels/Rotation/FRotationParticle.hpp create mode 100755 Src/Kernels/Rotation/FRotationParticleContainer.hpp delete mode 100755 Src/Kernels/Spherical/FSphericalParticle.hpp delete mode 100755 Tests/Kernels/testSphericalTsmNoTsm.cpp delete mode 100755 Tests/Utils/testMortonIndex.cpp diff --git a/Src/Arranger/FOctreeArranger.hpp b/Src/Arranger/FOctreeArranger.hpp index d5c074cf9..614e3c4e0 100755 --- a/Src/Arranger/FOctreeArranger.hpp +++ b/Src/Arranger/FOctreeArranger.hpp @@ -32,7 +32,7 @@ * to move the particles in the tree instead of building a new * tree. */ -template <class OctreeClass, class ContainerClass, class ParticleClass> +template <class OctreeClass, class ContainerClass, class ExtractorClass> class FOctreeArranger : FAssertable { OctreeClass* const tree; //< The tree to work on @@ -45,7 +45,7 @@ public: /** Arrange */ void rearrange(const int isPeriodic = DirNone){ // This vector is to keep the moving particles - FVector<ParticleClass> tomove; + ExtractorClass extractor; // For periodic const FReal boxWidth = tree->getBoxWidth(); @@ -53,14 +53,17 @@ public: const FPoint max(tree->getBoxCenter(),boxWidth/2); { // iterate on the leafs and found particle to remove + FVector<int> indexesToExtract; + typename OctreeClass::Iterator octreeIterator(tree); octreeIterator.gotoBottomLeft(); do{ const MortonIndex currentIndex = octreeIterator.getCurrentGlobalIndex(); - - typename ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListTargets()); - while( iter.hasNotFinished() ){ - FPoint partPos = iter.data().getPosition(); + ContainerClass* particles = octreeIterator.getCurrentLeaf()->getSrc(); + for(int idxPart = 0 ; idxPart < particles->getNbParticles(); ++idxPart){ + FPoint partPos( particles->getPositions()[0][idxPart], + particles->getPositions()[1][idxPart], + particles->getPositions()[2][idxPart] ); // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX if( TestPeriodicCondition(isPeriodic, DirPlusX) ){ while(partPos.getX() >= max.getX()){ @@ -119,24 +122,25 @@ public: printf("Application is exiting...\n"); } // set pos - iter.data().setPosition(partPos); + particles->getWPositions()[0][idxPart] = partPos.getX(); + particles->getWPositions()[1][idxPart] = partPos.getY(); + particles->getWPositions()[2][idxPart] = partPos.getZ(); - const MortonIndex particuleIndex = tree->getMortonFromPosition(iter.data().getPosition()); + const MortonIndex particuleIndex = tree->getMortonFromPosition(partPos); if(particuleIndex != currentIndex){ - tomove.push(iter.data()); - iter.remove(); - } - else { - iter.gotoNext(); + indexesToExtract.push(idxPart); } } + // remove from leaf + extractor.extractParticles(particles, indexesToExtract.data(), indexesToExtract.getSize()); + particles->removeParticles(indexesToExtract.data(), indexesToExtract.getSize()); + indexesToExtract.clear(); + } while(octreeIterator.moveRight()); } { // insert particles that moved - for(int idxPart = 0 ; idxPart < tomove.getSize() ; ++idxPart){ - tree->insert(tomove[idxPart]); - } + extractor.reinsertInTree(tree); } { // Remove empty leaves @@ -145,7 +149,7 @@ public: bool workOnNext = true; do{ // Empty leaf - if( octreeIterator.getCurrentListTargets()->getSize() == 0 ){ + if( octreeIterator.getCurrentListTargets()->getNbParticles() == 0 ){ const MortonIndex currentIndex = octreeIterator.getCurrentGlobalIndex(); workOnNext = octreeIterator.moveRight(); tree->removeLeaf( currentIndex ); diff --git a/Src/Components/FAbstractLeaf.hpp b/Src/Components/FAbstractLeaf.hpp index bb9271ccf..a14527a95 100755 --- a/Src/Components/FAbstractLeaf.hpp +++ b/Src/Components/FAbstractLeaf.hpp @@ -16,7 +16,8 @@ #ifndef FABSTRACTLEAF_HPP #define FABSTRACTLEAF_HPP - +#include "../Utils/FPoint.hpp" +#include "../Utils/FDebug.hpp" /** * @author Berenger Bramas (berenger.bramas@inria.fr) @@ -26,7 +27,7 @@ * This class is used to enable the use of typed particles * (source XOR target) or simple system (source AND target) */ -template< class ParticleClass, class ContainerClass > +template< class ContainerClass > class FAbstractLeaf { public: /** Default destructor */ @@ -39,7 +40,10 @@ public: * Depending on the system to use the class that inherit * this interface can sort the particle as they like. */ - virtual void push(const ParticleClass& particle) = 0; + template<typename... Args> + void push(const FPoint& /*inParticlePosition*/, Args ... /*args*/){ + FDEBUG( FDebug::Controller.write("Warning, push is not implemented!").write(FDebug::Flush) ); + } /** * To get all the sources in a leaf diff --git a/Src/Components/FAbstractParticle.hpp b/Src/Components/FAbstractParticleContainer.hpp similarity index 73% rename from Src/Components/FAbstractParticle.hpp rename to Src/Components/FAbstractParticleContainer.hpp index ab62efe00..0345163d4 100755 --- a/Src/Components/FAbstractParticle.hpp +++ b/Src/Components/FAbstractParticleContainer.hpp @@ -13,9 +13,11 @@ // "http://www.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== -#ifndef FABSTRACTPARTICLE_HPP -#define FABSTRACTPARTICLE_HPP +#ifndef FABSTRACTPARTICLECONTAINER_HPP +#define FABSTRACTPARTICLECONTAINER_HPP +#include "../Utils/FGlobal.hpp" +#include "../Utils/FDebug.hpp" /* forward declaration to avoid include */ class FPoint; @@ -36,20 +38,19 @@ class FPoint; * * @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 const FPoint& getPosition() const = 0; +class FAbstractParticleContainer { +public: + /** Default destructor */ + virtual ~FAbstractParticleContainer(){ + } + + template<typename... Args> + void push(const FPoint& /*inParticlePosition*/, Args ... /*args*/){ + FDEBUG( FDebug::Controller.write("Warning, push is not implemented!").write(FDebug::Flush) ); + } }; -#endif //FABSTRACTPARTICLE_HPP +#endif //FABSTRACTPARTICLECONTAINER_HPP diff --git a/Src/Components/FBasicCell.hpp b/Src/Components/FBasicCell.hpp index 81f435eda..647a50b99 100755 --- a/Src/Components/FBasicCell.hpp +++ b/Src/Components/FBasicCell.hpp @@ -17,7 +17,6 @@ #define FBASICCELL_HPP -#include "../Extensions/FExtendPosition.hpp" #include "../Extensions/FExtendMortonIndex.hpp" #include "../Extensions/FExtendCoordinate.hpp" diff --git a/Src/Components/FBasicParticleContainer.hpp b/Src/Components/FBasicParticleContainer.hpp new file mode 100755 index 000000000..7173fca9f --- /dev/null +++ b/Src/Components/FBasicParticleContainer.hpp @@ -0,0 +1,204 @@ +// =================================================================================== +// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner +// olivier.coulaud@inria.fr, berenger.bramas@inria.fr +// This software is a computer program whose purpose is to compute the FMM. +// +// This software is governed by the CeCILL-C and LGPL licenses and +// abiding by the rules of distribution of free software. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public and CeCILL-C Licenses for more details. +// "http://www.cecill.info". +// "http://www.gnu.org/licenses". +// =================================================================================== +#ifndef FBASICPARTICLECONTAINER_HPP +#define FBASICPARTICLECONTAINER_HPP + +#include "FAbstractParticleContainer.hpp" + +#include <type_traits> + +/** +* @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. +*/ +template <unsigned NbAttributesPerParticle, class AttributeClass = FReal > +class FBasicParticleContainer : public FAbstractParticleContainer { +protected: + int nbParticles; + FReal* positions[3]; + AttributeClass* attributes[NbAttributesPerParticle]; + + int allocatedParticles; + + template<int index> + void addParticleValue(const int /*insertPosition*/){ + } + + template<int index, typename... Args> + void addParticleValue(const int insertPosition, const AttributeClass value, Args... args){ + static_assert(index < NbAttributesPerParticle, "Index to get attributes is out of scope."); + attributes[index][insertPosition] = value; + addParticleValue<index+1>( insertPosition, args...); + } + +public: + FBasicParticleContainer(const FBasicParticleContainer&) = delete; + FBasicParticleContainer& operator=(const FBasicParticleContainer&) = delete; + + FBasicParticleContainer() : nbParticles(0), allocatedParticles(0){ + memset(positions, 0, sizeof(positions[0]) * 3); + memset(attributes, 0, sizeof(attributes[0]) * NbAttributesPerParticle); + } + + ~FBasicParticleContainer(){ + delete[] reinterpret_cast<char*>(positions[0]); + } + + int getNbParticles() const{ + return nbParticles; + } + + const FReal*const*const getPositions() const { + return positions; + } + + FReal*const*const getWPositions() { + return positions; + } + + AttributeClass* getAttribute(const int index) { + return attributes[index]; + } + + const AttributeClass* getAttribute(const int index) const { + return attributes[index]; + } + + template <int index> + AttributeClass* getAttribute() { + static_assert(index < NbAttributesPerParticle, "Index to get attributes is out of scope."); + return attributes[index]; + } + + template <int index> + const AttributeClass* getAttribute() const { + static_assert(index < NbAttributesPerParticle, "Index to get attributes is out of scope."); + return attributes[index]; + } + + template<typename... Args> + void push(const FPoint& inParticlePosition, Args... args){ + if( nbParticles == allocatedParticles ){ + allocatedParticles = FMath::Max(10,int(FReal(nbParticles+1)*1.5)); + FReal* newData = reinterpret_cast<FReal*>(new char[(sizeof(FReal)*3 + sizeof(AttributeClass)*NbAttributesPerParticle)*allocatedParticles]); + memset( newData, 0, (sizeof(FReal)*3 + sizeof(AttributeClass)*NbAttributesPerParticle)*allocatedParticles); + + const char*const toDelete = reinterpret_cast<const char*>(positions[0]); + for(int idx = 0 ; idx < 3 ; ++idx){ + memcpy(newData + (allocatedParticles * idx), positions[idx], sizeof(FReal) * nbParticles); + positions[idx] = newData + (allocatedParticles * idx); + } + AttributeClass* startAddress = reinterpret_cast<AttributeClass*>(positions[2] + allocatedParticles); + for(unsigned idx = 0 ; idx < NbAttributesPerParticle ; ++idx){ + memcpy(startAddress + (allocatedParticles * idx), attributes[idx], sizeof(AttributeClass) * nbParticles); + attributes[idx] = startAddress + (idx * allocatedParticles); + } + delete[] toDelete; + } + positions[0][nbParticles] = inParticlePosition.getX(); + positions[1][nbParticles] = inParticlePosition.getY(); + positions[2][nbParticles] = inParticlePosition.getZ(); + addParticleValue<0>( nbParticles, args...); + nbParticles += 1; + } + + template<typename... Args> + void push(const FPoint& inParticlePosition, const bool /*isTarget*/, Args... args){ + push(inParticlePosition, args...); + } + + void clear(){ + nbParticles = 0; + } + + /** Save the current cell in a buffer */ + void save(FBufferWriter& buffer) const{ + buffer << nbParticles; + for(int idx = 0 ; idx < 3 ; ++idx){ + buffer.write(positions[idx], nbParticles); + } + for(unsigned idx = 0 ; idx < NbAttributesPerParticle ; ++idx){ + buffer.write(attributes[idx], nbParticles); + } + } + /** Restore the current cell from a buffer */ + void restore(FBufferReader& buffer){ + buffer >> nbParticles; + if( nbParticles >= allocatedParticles ){ + allocatedParticles = FMath::Max(10,int(FReal(nbParticles+1)*1.5)); + FReal* newData = reinterpret_cast<FReal*>(new char[(sizeof(FReal)*3 + sizeof(AttributeClass)*NbAttributesPerParticle)*allocatedParticles]); + memset( newData, 0, (sizeof(FReal)*3 + sizeof(AttributeClass)*NbAttributesPerParticle)*allocatedParticles); + + delete[] reinterpret_cast<char*>(positions[0]); + for(int idx = 0 ; idx < 3 ; ++idx){ + positions[idx] = newData + (allocatedParticles * idx); + } + AttributeClass* startAddress = reinterpret_cast<AttributeClass*>(positions[2] + allocatedParticles); + for(unsigned idx = 0 ; idx < NbAttributesPerParticle ; ++idx){ + attributes[idx] = startAddress + (idx * allocatedParticles); + } + } + for(int idx = 0 ; idx < 3 ; ++idx){ + buffer.fillArray(positions[idx], nbParticles); + } + for(unsigned idx = 0 ; idx < NbAttributesPerParticle ; ++idx){ + buffer.fillArray(attributes[idx], nbParticles); + } + } + + /** to enable rearranging */ + void removeParticles(const int indexesToRemove[], const int nbParticlesToRemove){ + int offset = 1; + int idxIndexes = 1; + int idxIns = indexesToRemove[0] + 1; + for( ; idxIns < nbParticles && idxIndexes < nbParticlesToRemove ; ++idxIns){ + if( idxIns == indexesToRemove[idxIndexes] ){ + idxIndexes += 1; + offset += 1; + } + else{ + for(int idx = 0 ; idx < 3 ; ++idx){ + positions[idx][idxIns-offset] = positions[idx][idxIns]; + } + for(unsigned idx = 0 ; idx < NbAttributesPerParticle ; ++idx){ + attributes[idx][idxIns-offset] = attributes[idx][idxIns]; + } + } + } + for( ; idxIns < nbParticles ; ++idxIns){ + for(int idx = 0 ; idx < 3 ; ++idx){ + positions[idx][idxIns-offset] = positions[idx][idxIns]; + } + for(unsigned idx = 0 ; idx < NbAttributesPerParticle ; ++idx){ + attributes[idx][idxIns-offset] = attributes[idx][idxIns]; + } + } + nbParticles -= nbParticlesToRemove; + } + +}; + + +#endif //FBASICPARTICLECONTAINER_HPP + + diff --git a/Src/Components/FFmaParticle.hpp b/Src/Components/FFmaParticleContainer.hpp similarity index 60% rename from Src/Components/FFmaParticle.hpp rename to Src/Components/FFmaParticleContainer.hpp index 99f5ebf63..fcd2eed18 100755 --- a/Src/Components/FFmaParticle.hpp +++ b/Src/Components/FFmaParticleContainer.hpp @@ -13,12 +13,10 @@ // "http://www.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== -#ifndef FFmaPARTICLE_HPP -#define FFmaPARTICLE_HPP +#ifndef FFMAPARTICLECONTAINER_HPP +#define FFMAPARTICLECONTAINER_HPP - -#include "../Extensions/FExtendPosition.hpp" -#include "../Extensions/FExtendPhysicalValue.hpp" +#include "FBasicParticleContainer.hpp" /** * @author Berenger Bramas (berenger.bramas@inria.fr) @@ -26,23 +24,22 @@ * Please read the license * * This class defines a particle for FMA loader. -* As defined in FFmaLoader it needs {FBasicParticle,FExtendPhysicalValue} +* As defined in FFmaLoader it needs */ -class FFmaParticle : public FExtendPosition, public FExtendPhysicalValue { +class FFmaParticleContainer : public FBasicParticleContainer<1> { + typedef FBasicParticleContainer<1> Parent; + public: - /** Save the current cell in a buffer */ - void save(FBufferWriter& buffer) const{ - FExtendPosition::save(buffer); - FExtendPhysicalValue::save(buffer); + FReal* getPhysicalValues(){ + return Parent::getAttribute(0); } - /** Restore the current cell from a buffer */ - void restore(FBufferReader& buffer){ - FExtendPosition::restore(buffer); - FExtendPhysicalValue::restore(buffer); + + const FReal* getPhysicalValues() const { + return Parent::getAttribute(0); } }; -#endif //FFmaPARTICLE_HPP +#endif //FFMAPARTICLECONTAINER_HPP diff --git a/Src/Components/FSimpleLeaf.hpp b/Src/Components/FSimpleLeaf.hpp index 100893d5a..89942950f 100755 --- a/Src/Components/FSimpleLeaf.hpp +++ b/Src/Components/FSimpleLeaf.hpp @@ -27,8 +27,8 @@ * 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 ContainerClass> -class FSimpleLeaf : public FAbstractLeaf<ParticleClass,ContainerClass> { +template< class ContainerClass> +class FSimpleLeaf : public FAbstractLeaf<ContainerClass> { ContainerClass particles; public: @@ -40,8 +40,9 @@ public: * To add a new particle in the leaf * @param particle the new particle to store in the current leaf */ - void push(const ParticleClass& particle){ - this->particles.push(particle); + template<typename... Args> + void push(const FPoint& inParticlePosition, Args ... args){ + this->particles.push(inParticlePosition, args...); } /** diff --git a/Src/Components/FTestKernels.hpp b/Src/Components/FTestKernels.hpp index 2981ba79a..c9be456fa 100755 --- a/Src/Components/FTestKernels.hpp +++ b/Src/Components/FTestKernels.hpp @@ -83,8 +83,8 @@ public: /** After Downward */ void L2P(const CellClass* const local, ContainerClass*const particles){ // The particles is impacted by the parent cell - int*const particlesAttributes = targets->getDataDown(); - for(int idxPart = 0 ; idxPart < targets ; ++idxPart){ + long long int*const particlesAttributes = particles->getDataDown(); + for(int idxPart = 0 ; idxPart < particles->getNbParticles() ; ++idxPart){ particlesAttributes[idxPart] += local->getDataDown(); } } @@ -95,7 +95,7 @@ public: ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict sources, ContainerClass* const directNeighborsParticles[27], const int ){ // Each particles targeted is impacted by the particles sources - long long int inc = sources->getSize(); + long long int inc = sources->getNbParticles(); if(targets == sources){ inc -= 1; } @@ -105,8 +105,8 @@ public: } } - int*const particlesAttributes = targets->getDataDown(); - for(int idxPart = 0 ; idxPart < targets ; ++idxPart){ + long long int*const particlesAttributes = targets->getDataDown(); + for(int idxPart = 0 ; idxPart < targets->getNbParticles() ; ++idxPart){ particlesAttributes[idxPart] += inc; } } @@ -123,8 +123,8 @@ public: } } - int*const particlesAttributes = targets->getDataDown(); - for(int idxPart = 0 ; idxPart < targets ; ++idxPart){ + long long int*const particlesAttributes = targets->getDataDown(); + for(int idxPart = 0 ; idxPart < targets->getNbParticles() ; ++idxPart){ particlesAttributes[idxPart] += inc; } } @@ -140,15 +140,13 @@ void ValidateFMMAlgo(OctreeClass* const tree){ const int TreeHeight = tree->getHeight(); long long int NbPart = 0; { // Check that each particle has been summed with all other - typename OctreeClass::Iterator octreeIterator(tree); - octreeIterator.gotoBottomLeft(); - do{ - if(octreeIterator.getCurrentCell()->getDataUp() != octreeIterator.getCurrentListSrc()->getSize() ){ - std::cout << "Problem P2M : " << octreeIterator.getCurrentCell()->getDataUp() << - " (should be " << octreeIterator.getCurrentListSrc()->getSize() << ")\n"; + tree->forEachCellLeaf([&](CellClass* cell, LeafClass* leaf){ + if(cell->getDataUp() != leaf->getSrc()->getNbParticles() ){ + std::cout << "Problem P2M : " << cell->getDataUp() << + " (should be " << leaf->getSrc()->getNbParticles() << ")\n"; } - NbPart += octreeIterator.getCurrentListSrc()->getSize(); - } while(octreeIterator.moveRight()); + NbPart += leaf->getSrc()->getNbParticles(); + }); } { // Ceck if there is number of NbPart summed at level 1 typename OctreeClass::Iterator octreeIterator(tree); @@ -180,18 +178,14 @@ void ValidateFMMAlgo(OctreeClass* const tree){ typename OctreeClass::Iterator octreeIterator(tree); octreeIterator.gotoBottomLeft(); do{ - typename ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListTargets()); - const bool isUsingTsm = (octreeIterator.getCurrentListTargets() != octreeIterator.getCurrentListSrc()); - - while( iter.hasNotFinished() ){ - // If a particles has been impacted by less than NbPart - 1 (the current particle) - // there is a problem - if( (!isUsingTsm && iter.data().getDataDown() != NbPart - 1) || - (isUsingTsm && iter.data().getDataDown() != NbPart) ){ - std::cout << "Problem L2P + P2P : " << iter.data().getDataDown() << "(" << octreeIterator.getCurrentGlobalIndex() << ")\n"; + const long long int* dataDown = octreeIterator.getCurrentListTargets()->getDataDown(); + for(int idxPart = 0 ; idxPart < octreeIterator.getCurrentListTargets()->getNbParticles() ; ++idxPart){ + if( (!isUsingTsm && dataDown[idxPart] != NbPart - 1) || + (isUsingTsm && dataDown[idxPart] != NbPart) ){ + std::cout << "Problem L2P + P2P : " << dataDown[idxPart] << + "(" << octreeIterator.getCurrentGlobalIndex() << ")\n"; } - iter.gotoNext(); } } while(octreeIterator.moveRight()); } diff --git a/Src/Components/FTestParticle.hpp b/Src/Components/FTestParticle.hpp deleted file mode 100755 index d4287abdc..000000000 --- a/Src/Components/FTestParticle.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== -#ifndef FTESTPARTICLE_HPP -#define FTESTPARTICLE_HPP - - -#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. -* -* Particles just need the data down (after and run with FTestKernel the -* value shoud be NB PARTICLES (-1)). -*/ -class FTestParticle : public FBasicParticle { -protected: - // To store data during downard pass - long long int dataDown; -public: - FTestParticle(): dataDown(0){ - } - - /** Default destructor */ - virtual ~FTestParticle(){ - } - - /** Get the down data */ - long long int getDataDown() const { - return this->dataDown; - } - - /** Set down data */ - void setDataDown(const long long int inData){ - this->dataDown = inData; - } - - ////////////////////////////////////////////////// - - /** Save the current cell in a buffer */ - void save(FBufferWriter& buffer) const{ - FBasicParticle::save(buffer); - buffer << dataDown; - } - - /** Restore the current cell from a buffer */ - void restore(FBufferReader& buffer){ - FBasicParticle::restore(buffer); - buffer >> dataDown; - } -}; - - -#endif //FTESTPARTICLE_HPP - - diff --git a/Src/Components/FBasicParticle.hpp b/Src/Components/FTestParticleContainer.hpp similarity index 57% rename from Src/Components/FBasicParticle.hpp rename to Src/Components/FTestParticleContainer.hpp index 52cc2be83..61593c554 100755 --- a/Src/Components/FBasicParticle.hpp +++ b/Src/Components/FTestParticleContainer.hpp @@ -13,36 +13,37 @@ // "http://www.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== -#ifndef FBASICPARTICLE_HPP -#define FBASICPARTICLE_HPP +#ifndef FTESTPARTICLECONTAINER_HPP +#define FTESTPARTICLECONTAINER_HPP -#include "../Extensions/FExtendPosition.hpp" +#include "FBasicParticleContainer.hpp" /** * @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FBasicParticle +* @class FTestParticle * 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. +* This class is used in the FTestKernels, please +* look at this class to know whit it is. +* +* Particles just need the data down (after and run with FTestKernel the +* value shoud be NB PARTICLES (-1)). */ -class FBasicParticle : public FExtendPosition{ +class FTestParticleContainer : public FBasicParticleContainer<1, long long int> { + typedef FBasicParticleContainer<1, long long int> Parent; + public: - /** Save the current cell in a buffer */ - void save(FBufferWriter& buffer) const{ - FExtendPosition::save(buffer); + long long int* getDataDown(){ + return Parent::getAttribute(0); } - /** Restore the current cell from a buffer */ - void restore(FBufferReader& buffer){ - FExtendPosition::restore(buffer); + + const long long int* getDataDown() const { + return Parent::getAttribute(0); } }; -#endif //FBASICPARTICLE_HPP +#endif //FTESTPARTICLECONTAINER_HPP diff --git a/Src/Components/FTypedLeaf.hpp b/Src/Components/FTypedLeaf.hpp index 23edff486..1dc1c1e39 100755 --- a/Src/Components/FTypedLeaf.hpp +++ b/Src/Components/FTypedLeaf.hpp @@ -30,8 +30,8 @@ * * Particles should be typed to enable targets/sources difference. */ -template< class ParticleClass , class ContainerClass> -class FTypedLeaf : public FAbstractLeaf<ParticleClass,ContainerClass>, public FAssertable { +template< class ContainerClass> +class FTypedLeaf : public FAbstractLeaf<ContainerClass>, public FAssertable { ContainerClass sources; //< The sources containers ContainerClass targets; //< The targets containers @@ -44,11 +44,10 @@ public: * To add a new particle in the leaf * @param particle the new particle */ - void push(const ParticleClass& particle){ - // Test if is source or target particle - if(particle.isTarget()) this->targets.push(particle); - else if(particle.isSource()) this->sources.push(particle); - else fassert(false, "Error particle has undefined type.", __LINE__, __FILE__); + template<typename... Args> + void push(const FPoint& inParticlePosition, const bool isTarget, Args ... args){ + if(isTarget) targets.push(inParticlePosition, args...); + else sources.push(inParticlePosition, args...); } /** diff --git a/Src/Containers/FOctree.hpp b/Src/Containers/FOctree.hpp index 5dca8c7a6..21b6b8648 100755 --- a/Src/Containers/FOctree.hpp +++ b/Src/Containers/FOctree.hpp @@ -4,13 +4,13 @@ // This software is a computer program whose purpose is to compute the FMM. // // This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// +// abiding by the rules of distribution of free software. +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". +// "http://www.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== #ifndef FOCTREE_HPP @@ -50,10 +50,12 @@ * If the octree as an height H, then it goes from 0 to H-1 * at level 0 the space is not split */ -template< class ParticleClass, class CellClass, class ContainerClass, class LeafClass> +template< class CellClass, class ContainerClass, class LeafClass> class FOctree : protected FAssertable, public FNoCopyable { + typedef FSubOctreeWithLeafs< CellClass , ContainerClass, LeafClass> SubOctreeWithLeaves; + typedef FSubOctree< CellClass , ContainerClass, LeafClass> SubOctree; - FAbstractSubOctree< ParticleClass, CellClass , ContainerClass, LeafClass>* root; //< root suboctree + FAbstractSubOctree< CellClass , ContainerClass, LeafClass>* root; //< root suboctree FReal*const boxWidthAtLevel; //< to store the width of each boxs at all levels @@ -116,10 +118,10 @@ public: fassert(subHeight <= height - 1, "Subheight cannot be greater than height", __LINE__, __FILE__ ); // Does we only need one suboctree? if(subHeight == height - 1){ - root = new FSubOctreeWithLeafs< ParticleClass, CellClass , ContainerClass, LeafClass>(0, 0, this->subHeight, 1); + root = new FSubOctreeWithLeafs< CellClass , ContainerClass, LeafClass>(0, 0, this->subHeight, 1); } else {// if(subHeight < height - 1) - root = new FSubOctree< ParticleClass, CellClass , ContainerClass, LeafClass>(0, 0, this->subHeight, 1); + root = new FSubOctree< CellClass , ContainerClass, LeafClass>(0, 0, this->subHeight, 1); } FReal tempWidth = this->boxWidth; @@ -185,10 +187,29 @@ public: * ask node to insert this particle * @param inParticle the particle to insert (must inherite from FAbstractParticle) */ - void insert(const ParticleClass& inParticle){ - const FTreeCoordinate host = getCoordinateFromPosition( inParticle.getPosition() ); + template<typename... Args> + void insert(const FPoint& inParticlePosition, Args... args){ + const FTreeCoordinate host = getCoordinateFromPosition( inParticlePosition ); const MortonIndex particleIndex = host.getMortonIndex(leafIndex); - root->insert( particleIndex, host, inParticle, this->height); + if(root->isLeafPart()){ + ((SubOctreeWithLeaves*)root)->insert( particleIndex, host, this->height, inParticlePosition, args... ); + } + else{ + ((SubOctree*)root)->insert( particleIndex, host, this->height, inParticlePosition, args... ); + } + } + + /** Remove a leaf from its morton index + * @param indexToRemove the index of the leaf to remove + */ + LeafClass* createLeaf(const MortonIndex indexToCreate ){ + const FTreeCoordinate host(indexToCreate,this->height-1); + if(root->isLeafPart()){ + return ((SubOctreeWithLeaves*)root)->createLeaf( indexToCreate, host, this->height ); + } + else{ + return ((SubOctree*)root)->createLeaf( indexToCreate, host, this->height ); + } } /** Remove a leaf from its morton index @@ -214,18 +235,18 @@ public: * depending if we are working on the bottom of the tree. */ union SubOctreeTypes { - FAbstractSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass>* tree; //< Usual pointer to work - FSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass>* middleTree; //< To access to sub-octree under - FSubOctreeWithLeafs<ParticleClass,CellClass,ContainerClass,LeafClass>* leafTree;//< To access to particles lists + FAbstractSubOctree<CellClass,ContainerClass,LeafClass>* tree; //< Usual pointer to work + FSubOctree<CellClass,ContainerClass,LeafClass>* middleTree; //< To access to sub-octree under + FSubOctreeWithLeafs<CellClass,ContainerClass,LeafClass>* leafTree;//< To access to particles lists }; /** * This class is a const SubOctreeTypes */ union SubOctreeTypesConst { - const FAbstractSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass>* tree; //< Usual pointer to work - const FSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass>* middleTree; //< To access to sub-octree under - const FSubOctreeWithLeafs<ParticleClass,CellClass,ContainerClass,LeafClass>* leafTree;//< To access to particles lists + const FAbstractSubOctree<CellClass,ContainerClass,LeafClass>* tree; //< Usual pointer to work + const FSubOctree<CellClass,ContainerClass,LeafClass>* middleTree; //< To access to sub-octree under + const FSubOctreeWithLeafs<CellClass,ContainerClass,LeafClass>* leafTree;//< To access to particles lists }; /** @@ -1129,15 +1150,9 @@ public: Iterator octreeIterator(this); octreeIterator.gotoBottomLeft(); - Iterator avoidGoLeft(octreeIterator); - - for(int idx = 0 ; idx < this->height - 1 ; ++idx ){ - do{ - function(octreeIterator.getCurrentCell(),octreeIterator.getCurrentLeaf()); - } while(octreeIterator.moveRight()); - avoidGoLeft.moveUp(); - octreeIterator = avoidGoLeft; - } + do{ + function(octreeIterator.getCurrentCell(),octreeIterator.getCurrentLeaf()); + } while(octreeIterator.moveRight()); } }; diff --git a/Src/Containers/FSubOctree.hpp b/Src/Containers/FSubOctree.hpp index 108072fd1..a467e818e 100755 --- a/Src/Containers/FSubOctree.hpp +++ b/Src/Containers/FSubOctree.hpp @@ -4,13 +4,13 @@ // This software is a computer program whose purpose is to compute the FMM. // // This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// +// abiding by the rules of distribution of free software. +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". +// "http://www.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== #ifndef FSUBOCTREE_HPP @@ -32,7 +32,7 @@ * * 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. * @@ -47,7 +47,7 @@ * Please refere to testOctree.cpp to see an example * @warning Give the particleClass & cellClass */ -template< class ParticleClass, class CellClass , class ContainerClass, class LeafClass> +template< class CellClass , class ContainerClass, class LeafClass> class FAbstractSubOctree : protected FAssertable{ protected: @@ -232,7 +232,10 @@ public: * @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, const FTreeCoordinate& host, const ParticleClass& inParticle, const int inTreeHeight) = 0; + /*template<typename... Args> + void insert(const MortonIndex index, const FTreeCoordinate& host, const int inTreeHeight, const FPoint& inParticlePosition, + Args... args){ + }*/ /** * Remove a leaf and every cells if needed @@ -331,18 +334,17 @@ public: * Please refere to testOctree.cpp to see an example. * @warning Give the particleClass & cellClass */ -template< class ParticleClass, class CellClass , class ContainerClass, class LeafClass> -class FSubOctreeWithLeafs : public FAbstractSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass> { +template< class CellClass , class ContainerClass, class LeafClass> +class FSubOctreeWithLeafs : public FAbstractSubOctree<CellClass,ContainerClass,LeafClass> { private: - typedef FAbstractSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass> Parent; + typedef FAbstractSubOctree<CellClass,ContainerClass,LeafClass> Parent; LeafClass** leafs; //< Leafs array - /** Disable copy */ - FSubOctreeWithLeafs(const FSubOctreeWithLeafs&){} - FSubOctreeWithLeafs& operator=(const FSubOctreeWithLeafs&){return *this;} +public: + FSubOctreeWithLeafs(const FSubOctreeWithLeafs&) = delete; + FSubOctreeWithLeafs& operator=(const FSubOctreeWithLeafs&) = delete; -public: /** * Constructor * Allocate the leafs array @@ -350,9 +352,9 @@ public: * @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,ContainerClass,LeafClass>* const inParent, const int inIndexInParent, + FSubOctreeWithLeafs(FAbstractSubOctree<CellClass,ContainerClass,LeafClass>* const inParent, const int inIndexInParent, const int inSubOctreeHeight, const int inSubOctreePosition) : - FAbstractSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass>(inParent, inIndexInParent, inSubOctreeHeight, inSubOctreePosition, true) { + FAbstractSubOctree<CellClass,ContainerClass,LeafClass>(inParent, inIndexInParent, inSubOctreeHeight, inSubOctreePosition, true) { const int cellsAtLeafLevel = 1 << (3 * inSubOctreeHeight); @@ -377,7 +379,9 @@ public: /** * Refer to FAbstractSubOctree::insert */ - void insert(const MortonIndex index, const FTreeCoordinate& host, const ParticleClass& inParticle, const int inTreeHeight){ + template<typename... Args> + void insert(const MortonIndex index, const FTreeCoordinate& host, const int inTreeHeight, const FPoint& inParticlePosition, + Args... args){ // Get the morton index for the leaf level const MortonIndex arrayIndex = Parent::getLeafIndex(index,inTreeHeight); // is there already a leaf? @@ -387,7 +391,20 @@ public: Parent::newLeafInserted( int(arrayIndex) , index, host); } // add particle to leaf list - this->leafs[arrayIndex]->push(inParticle); + this->leafs[arrayIndex]->push(inParticlePosition, args... ); + } + + LeafClass* createLeaf(const MortonIndex index, const FTreeCoordinate& host, const int inTreeHeight){ + // Get the morton index for the leaf level + const MortonIndex arrayIndex = Parent::getLeafIndex(index,inTreeHeight); + // is there already a leaf? + if( !this->leafs[arrayIndex] ){ + this->leafs[arrayIndex] = new LeafClass(); + + Parent::newLeafInserted( int(arrayIndex) , index, host); + } + // add particle to leaf list + return this->leafs[arrayIndex]; } /** @@ -462,18 +479,19 @@ public: * * @warning Give the particleClass & cellClass */ -template< class ParticleClass, class CellClass , class ContainerClass, class LeafClass> -class FSubOctree : public FAbstractSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass> { +template< class CellClass , class ContainerClass, class LeafClass> +class FSubOctree : public FAbstractSubOctree<CellClass,ContainerClass,LeafClass> { private: - typedef FAbstractSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass> Parent; + typedef FAbstractSubOctree<CellClass,ContainerClass,LeafClass> Parent; + typedef FSubOctreeWithLeafs<CellClass,ContainerClass,LeafClass> SubOctreeWithLeaf; Parent** subleafs; //< Last levels is composed of suboctree - /** Disable copy */ - FSubOctree(const FSubOctree&){} - FSubOctree& operator=(const FSubOctree&){return *this;} +public: + + FSubOctree(const FSubOctree&) = delete; + FSubOctree& operator=(const FSubOctree&) = delete; -public: /** * Constructor * Allocate the subleafs array @@ -481,9 +499,9 @@ public: * @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,ContainerClass,LeafClass>* const inParent, const int inIndexInParent, + FSubOctree(FAbstractSubOctree<CellClass,ContainerClass,LeafClass>* const inParent, const int inIndexInParent, const int inSubOctreeHeight, const int inSubOctreePosition) : - FAbstractSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass>(inParent, inIndexInParent, inSubOctreeHeight, inSubOctreePosition, false) { + FAbstractSubOctree<CellClass,ContainerClass,LeafClass>(inParent, inIndexInParent, inSubOctreeHeight, inSubOctreePosition, false) { const int cellsAtLeafLevel = 1 << (3 * inSubOctreeHeight); @@ -503,10 +521,46 @@ public: delete [] this->subleafs; } - /** - * Refer to FAbstractSubOctree::insert - */ - void insert(const MortonIndex index, const FTreeCoordinate& host, const ParticleClass& inParticle, const int inTreeHeight){ + + template<typename... Args> + void insert(const MortonIndex index, const FTreeCoordinate& host, const int inTreeHeight, const FPoint& inParticlePosition, + Args... args){ + // We need the morton index at the bottom level of this sub octree + // so we remove the right side + const MortonIndex arrayIndex = Parent::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,int(arrayIndex),nextSubOctreeHeight,nextSubOctreePosition); + } + // Or next suboctree contains the reail leaf! + else{ + this->subleafs[arrayIndex] = new SubOctreeWithLeaf(this,int(arrayIndex),nextSubOctreeHeight,nextSubOctreePosition); + } + + const FTreeCoordinate hostAtLevel( + host.getX() >> (inTreeHeight - nextSubOctreePosition ), + host.getY() >> (inTreeHeight - nextSubOctreePosition ), + host.getZ() >> (inTreeHeight - nextSubOctreePosition )); + + // We need to inform parent class + Parent::newLeafInserted( int(arrayIndex), index >> (3 * (inTreeHeight-nextSubOctreePosition) ), hostAtLevel); + } + // Ask next suboctree to insert the particle + if(this->subleafs[arrayIndex]->isLeafPart()){ + ((SubOctreeWithLeaf*)this->subleafs[arrayIndex])->insert( index, host, inTreeHeight, inParticlePosition, args... ); + } + else{ + ((FSubOctree*)this->subleafs[arrayIndex])->insert( index, host, inTreeHeight, inParticlePosition, args... ); + } + } + + LeafClass* createLeaf(const MortonIndex index, const FTreeCoordinate& host, const int inTreeHeight){ // We need the morton index at the bottom level of this sub octree // so we remove the right side const MortonIndex arrayIndex = Parent::getLeafIndex(index,inTreeHeight); @@ -522,7 +576,7 @@ public: } // Or next suboctree contains the reail leaf! else{ - this->subleafs[arrayIndex] = new FSubOctreeWithLeafs<ParticleClass,CellClass,ContainerClass,LeafClass>(this,int(arrayIndex),nextSubOctreeHeight,nextSubOctreePosition); + this->subleafs[arrayIndex] = new SubOctreeWithLeaf(this,int(arrayIndex),nextSubOctreeHeight,nextSubOctreePosition); } const FTreeCoordinate hostAtLevel( @@ -534,7 +588,12 @@ public: Parent::newLeafInserted( int(arrayIndex), index >> (3 * (inTreeHeight-nextSubOctreePosition) ), hostAtLevel); } // Ask next suboctree to insert the particle - this->subleafs[arrayIndex]->insert( index, host, inParticle, inTreeHeight); + if(this->subleafs[arrayIndex]->isLeafPart()){ + return ((SubOctreeWithLeaf*)this->subleafs[arrayIndex])->createLeaf( index, host, inTreeHeight ); + } + else{ + return ((FSubOctree*)this->subleafs[arrayIndex])->createLeaf( index, host, inTreeHeight ); + } } /** @@ -556,14 +615,14 @@ public: /** 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,ContainerClass,LeafClass>* leafs(const int index) { + FAbstractSubOctree<CellClass,ContainerClass,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,ContainerClass,LeafClass>* leafs(const int index) const { + const FAbstractSubOctree<CellClass,ContainerClass,LeafClass>* leafs(const int index) const { return this->subleafs[index]; } }; diff --git a/Src/Containers/FTreeCoordinate.hpp b/Src/Containers/FTreeCoordinate.hpp index f8eeeb0e6..d3d9eef7d 100755 --- a/Src/Containers/FTreeCoordinate.hpp +++ b/Src/Containers/FTreeCoordinate.hpp @@ -42,6 +42,11 @@ public: data[0] = data[1] = data[2] = 0; } + /** Default constructor (position = {0,0,0})*/ + explicit FTreeCoordinate(const MortonIndex mindex, const int indexLevel) { + setPositionFromMorton(mindex, indexLevel); + } + /** * Default constructor * @param inX the x @@ -249,6 +254,23 @@ public: void restore(FBufferReader& buffer) { buffer >> data[0] >> data[1] >> data[2]; } + + static std::string MortonToBinary(MortonIndex index, int level){ + std::string str; + int bits = 1 << ((level * 3) - 1); + int dim = 0; + while(bits){ + if(index & bits) str.append("1"); + else str.append("0"); + bits >>= 1; + // we put a dot each 3 values + if(++dim == 3){ + str.append("."); + dim = 0; + } + } + return str; + } }; diff --git a/Src/Core/FFmmAlgorithm.hpp b/Src/Core/FFmmAlgorithm.hpp index 356298a98..aa0027ad8 100755 --- a/Src/Core/FFmmAlgorithm.hpp +++ b/Src/Core/FFmmAlgorithm.hpp @@ -38,7 +38,7 @@ * * Of course this class does not deallocate pointer given in arguements. */ -template<class OctreeClass, class ParticleClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> +template<class OctreeClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> class FFmmAlgorithm : protected FAssertable{ OctreeClass* const tree; //< The octree to work on diff --git a/Src/Core/FFmmAlgorithmPeriodic.hpp b/Src/Core/FFmmAlgorithmPeriodic.hpp index 5e28d5441..0caded4a1 100755 --- a/Src/Core/FFmmAlgorithmPeriodic.hpp +++ b/Src/Core/FFmmAlgorithmPeriodic.hpp @@ -40,7 +40,7 @@ * * Of course this class does not deallocate pointer given in arguements. */ -template<class OctreeClass, class ParticleClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> +template<class OctreeClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> class FFmmAlgorithmPeriodic : protected FAssertable{ OctreeClass* const tree; //< The octree to work on @@ -294,12 +294,15 @@ public: periodicNeighbors[idxNeig] = neighbors[idxNeig]; neighbors[idxNeig] = 0; ++periodicNeighborsCounter; - typename ContainerClass::BasicIterator iter(*periodicNeighbors[idxNeig]); - while( iter.hasNotFinished() ){ - iter.data().incPosition(boxWidth * FReal(offsets[idxNeig].getX()), - boxWidth * FReal(offsets[idxNeig].getY()), - boxWidth * FReal(offsets[idxNeig].getZ())); - iter.gotoNext(); + + FReal*const positionsX = periodicNeighbors[idxNeig]->getWPositions()[0]; + FReal*const positionsY = periodicNeighbors[idxNeig]->getWPositions()[1]; + FReal*const positionsZ = periodicNeighbors[idxNeig]->getWPositions()[2]; + + for(int idxPart = 0; idxPart < periodicNeighbors[idxNeig]->getNbParticles() ; ++idxPart){ + positionsX[idxPart] += boxWidth * FReal(offsets[idxNeig].getX()); + positionsY[idxPart] += boxWidth * FReal(offsets[idxNeig].getY()); + positionsZ[idxPart] += boxWidth * FReal(offsets[idxNeig].getZ()); } } } @@ -310,13 +313,15 @@ public: FDEBUG(computationCounterP2P.tac()); for(int idxNeig = 0 ; idxNeig < 27 ; ++idxNeig){ - if( periodicNeighbors[idxNeig] ){ - typename ContainerClass::BasicIterator iter(*periodicNeighbors[idxNeig]); - while( iter.hasNotFinished() ){ - iter.data().incPosition(-boxWidth * FReal(offsets[idxNeig].getX()), - -boxWidth * FReal(offsets[idxNeig].getY()), - -boxWidth * FReal(offsets[idxNeig].getZ())); - iter.gotoNext(); + if( periodicNeighbors[idxNeig] ){ + FReal*const positionsX = periodicNeighbors[idxNeig]->getWPositions()[0]; + FReal*const positionsY = periodicNeighbors[idxNeig]->getWPositions()[1]; + FReal*const positionsZ = periodicNeighbors[idxNeig]->getWPositions()[2]; + + for(int idxPart = 0; idxPart < periodicNeighbors[idxNeig]->getNbParticles() ; ++idxPart){ + positionsX[idxPart] -= boxWidth * FReal(offsets[idxNeig].getX()); + positionsY[idxPart] -= boxWidth * FReal(offsets[idxNeig].getY()); + positionsZ[idxPart] -= boxWidth * FReal(offsets[idxNeig].getZ()); } } } diff --git a/Src/Core/FFmmAlgorithmSectionTask.hpp b/Src/Core/FFmmAlgorithmSectionTask.hpp index 996c9ea5f..4878ab861 100755 --- a/Src/Core/FFmmAlgorithmSectionTask.hpp +++ b/Src/Core/FFmmAlgorithmSectionTask.hpp @@ -38,7 +38,7 @@ * * Of course this class does not deallocate pointer given in arguements. */ -template<class OctreeClass, class ParticleClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> +template<class OctreeClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> class FFmmAlgorithmSectionTask : protected FAssertable{ OctreeClass* const tree; //< The octree to work on diff --git a/Src/Core/FFmmAlgorithmTask.hpp b/Src/Core/FFmmAlgorithmTask.hpp index f4a3aa351..76e8d322f 100755 --- a/Src/Core/FFmmAlgorithmTask.hpp +++ b/Src/Core/FFmmAlgorithmTask.hpp @@ -38,7 +38,7 @@ * * Of course this class does not deallocate pointer given in arguements. */ -template<class OctreeClass, class ParticleClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> +template<class OctreeClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> class FFmmAlgorithmTask : protected FAssertable{ OctreeClass* const tree; //< The octree to work on diff --git a/Src/Core/FFmmAlgorithmThread.hpp b/Src/Core/FFmmAlgorithmThread.hpp index a3ff19caa..b47ba8b61 100755 --- a/Src/Core/FFmmAlgorithmThread.hpp +++ b/Src/Core/FFmmAlgorithmThread.hpp @@ -43,7 +43,7 @@ * * When using this algorithm the P2P is thread safe. */ -template<class OctreeClass, class ParticleClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> +template<class OctreeClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> class FFmmAlgorithmThread : protected FAssertable{ OctreeClass* const tree; //< The octree to work on KernelClass** kernels; //< The kernels diff --git a/Src/Core/FFmmAlgorithmThreadProc.hpp b/Src/Core/FFmmAlgorithmThreadProc.hpp index 27963b1b1..fc119d77d 100755 --- a/Src/Core/FFmmAlgorithmThreadProc.hpp +++ b/Src/Core/FFmmAlgorithmThreadProc.hpp @@ -55,7 +55,7 @@ * --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes * ./Tests/testFmmAlgorithmProc ../Data/testLoaderSmall.fma.tmp */ -template<class OctreeClass, class ParticleClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> +template<class OctreeClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> class FFmmAlgorithmThreadProc : protected FAssertable { static const int MaxSizePerCell = 1024; diff --git a/Src/Core/FFmmAlgorithmThreadTsm.hpp b/Src/Core/FFmmAlgorithmThreadTsm.hpp index a992a2c89..d1d68190e 100755 --- a/Src/Core/FFmmAlgorithmThreadTsm.hpp +++ b/Src/Core/FFmmAlgorithmThreadTsm.hpp @@ -44,7 +44,7 @@ * Because this is a Target source model you do not need the P2P to be safe. * You should not write on sources in the P2P method! */ -template<class OctreeClass, class ParticleClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> +template<class OctreeClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> class FFmmAlgorithmThreadTsm : protected FAssertable{ OctreeClass* const tree; //< The octree to work on KernelClass** kernels; //< The kernels @@ -140,11 +140,11 @@ public: // We need the current cell that represent the leaf // and the list of particles ContainerClass* const sources = iterArray[idxLeafs].getCurrentListSrc(); - if(sources->getSize()){ + if(sources->getNbParticles()){ iterArray[idxLeafs].getCurrentCell()->setSrcChildTrue(); myThreadkernels->P2M( iterArray[idxLeafs].getCurrentCell() , sources); } - if(iterArray[idxLeafs].getCurrentListTargets()->getSize()){ + if(iterArray[idxLeafs].getCurrentListTargets()->getNbParticles()){ iterArray[idxLeafs].getCurrentCell()->setTargetsChildTrue(); } } diff --git a/Src/Core/FFmmAlgorithmTsm.hpp b/Src/Core/FFmmAlgorithmTsm.hpp index d5b55e7a8..8d4ba360d 100755 --- a/Src/Core/FFmmAlgorithmTsm.hpp +++ b/Src/Core/FFmmAlgorithmTsm.hpp @@ -38,7 +38,7 @@ * * The differences with FmmAlgorithm is that it used target source model. */ -template<class OctreeClass, class ParticleClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> +template<class OctreeClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass> class FFmmAlgorithmTsm : protected FAssertable{ OctreeClass* const tree; //< The octree to work on @@ -103,11 +103,11 @@ public: // and the list of particles FDEBUG(computationCounter.tic()); ContainerClass* const sources = octreeIterator.getCurrentListSrc(); - if(sources->getSize()){ + if(sources->getNbParticles()){ octreeIterator.getCurrentCell()->setSrcChildTrue(); kernels->P2M( octreeIterator.getCurrentCell() , sources); } - if(octreeIterator.getCurrentListTargets()->getSize()){ + if(octreeIterator.getCurrentListTargets()->getNbParticles()){ octreeIterator.getCurrentCell()->setTargetsChildTrue(); } FDEBUG(computationCounter.tac()); diff --git a/Src/Extensions/FExtendForces.hpp b/Src/Extensions/FExtendForces.hpp deleted file mode 100755 index 9604853a6..000000000 --- a/Src/Extensions/FExtendForces.hpp +++ /dev/null @@ -1,87 +0,0 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== -#ifndef FEXTENDFORCES_HPP -#define FEXTENDFORCES_HPP - - -#include "../Utils/FGlobal.hpp" -#include "../Utils/FPoint.hpp" -#include "../Containers/FBufferReader.hpp" -#include "../Containers/FBufferWriter.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: - FPoint forces; //< 3D vector stored in a position object - -public: - /** Default constructor */ - FExtendForces() { - } - - /** Copy constructor */ - FExtendForces(const FExtendForces& other) : forces(other.forces) { - } - - /** Copy operator */ - FExtendForces& operator=(const FExtendForces& other) { - this->forces = other.forces; - return *this; - } - - /** Return the forces */ - const FPoint& getForces() const { - return this->forces; - } - - /** Set Forces */ - void incForces(const FPoint& inForces) { - this->forces += inForces; - } - - /** Set Forces with 3 FReals */ - void incForces(const FReal inFx, const FReal inFy, const FReal inFz) { - this->forces.incX(inFx); - this->forces.incY(inFy); - this->forces.incZ(inFz); - } - - /** set the forces from 3 variables */ - void setForces(const FReal inFx, const FReal inFy, const FReal inFz) { - this->forces.setPosition(inFx , inFy, inFz); - } - - /** Save current object */ - void save(FBufferWriter& buffer) const { - forces.save(buffer); - } - /** Retrieve current object */ - void restore(FBufferReader& buffer) { - forces.restore(buffer); - } -}; - - -#endif //FEXTENDFORCES_HPP - - diff --git a/Src/Extensions/FExtendParticleType.hpp b/Src/Extensions/FExtendParticleType.hpp deleted file mode 100755 index 19c749058..000000000 --- a/Src/Extensions/FExtendParticleType.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== -#ifndef FEXTENDPARTICLETYPE_HPP -#define FEXTENDPARTICLETYPE_HPP - -#include "../Containers/FBufferReader.hpp" -#include "../Containers/FBufferWriter.hpp" - - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FExtendParticleType -* Please read the license -* This class is an extenssion. -* It proposes a target/source extenssion for particles. -*/ -class FExtendParticleType { -protected: - /** Particle potential type */ - enum Type { - Source, - Target, - Undef - }; - - /** Current type */ - Type type; - -public: - /** Default constructor */ - FExtendParticleType(const Type inType = Undef) : type(inType) { - } - - /** Copy constructor */ - FExtendParticleType(const FExtendParticleType& other) : type(other.type) { - } - - /** 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; - } - - /** Save current object */ - void save(FBufferWriter& buffer) const { - buffer << type; - } - /** Retrieve current object */ - void restore(FBufferReader& buffer) { - buffer >> type; - } -}; - - -#endif //FEXTENDPARTICLETYPE_HPP - - diff --git a/Src/Extensions/FExtendPhysicalValue.hpp b/Src/Extensions/FExtendPhysicalValue.hpp deleted file mode 100755 index e98aff2be..000000000 --- a/Src/Extensions/FExtendPhysicalValue.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== -#ifndef FExtendPhysicalValue_HPP -#define FExtendPhysicalValue_HPP - - -#include "../Utils/FGlobal.hpp" -#include "../Containers/FBufferReader.hpp" -#include "../Containers/FBufferWriter.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) { - } - - /** 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; - } - - /** Save current object */ - void save(FBufferWriter& buffer) const { - buffer << physicalValue; - } - /** Retrieve current object */ - void restore(FBufferReader& buffer) { - buffer >> physicalValue; - } - -}; - - -#endif //FExtendPhysicalValue_HPP - - diff --git a/Src/Extensions/FExtendPosition.hpp b/Src/Extensions/FExtendPosition.hpp deleted file mode 100755 index 5fa3a3231..000000000 --- a/Src/Extensions/FExtendPosition.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== -#ifndef FEXTENDPOSITION_HPP -#define FEXTENDPOSITION_HPP - - -#include "../Utils/FGlobal.hpp" -#include "../Utils/FPoint.hpp" -#include "../Containers/FBufferReader.hpp" -#include "../Containers/FBufferWriter.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FExtendPosition -* Please read the license -* This class is an extenssion. -* It proposes a position from a FPoint. -*/ -class FExtendPosition { -protected: - FPoint position; //< The position - -public: - /** Default constructor */ - FExtendPosition() { - } - - /** Copy constructor */ - FExtendPosition(const FExtendPosition& other) : position(other.position) { - } - - /** Copy operator */ - FExtendPosition& operator=(const FExtendPosition& other) { - this->position = other.position; - return *this; - } - - /** To get the position */ - const FPoint& getPosition() const { - return this->position; - } - - /** To set the position */ - void setPosition(const FPoint& 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); - } - - /** Set Position */ - void incPosition(const FPoint& inPosition) { - this->position += inPosition; - } - - /** Set Position with 3 FReals */ - void incPosition(const FReal inPx, const FReal inPy, const FReal inPz) { - this->position.incX(inPx); - this->position.incY(inPy); - this->position.incZ(inPz); - } - - /** Save current object */ - void save(FBufferWriter& buffer) const { - position.save(buffer); - } - /** Retrieve current object */ - void restore(FBufferReader& buffer) { - position.restore(buffer); - } -}; - - -#endif //FEXTENDPOSITION_HPP - - diff --git a/Src/Extensions/FExtendPotential.hpp b/Src/Extensions/FExtendPotential.hpp deleted file mode 100755 index 8178a3519..000000000 --- a/Src/Extensions/FExtendPotential.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== -#ifndef FEXTENDPOTENTIAL_HPP -#define FEXTENDPOTENTIAL_HPP - - -#include "../Utils/FGlobal.hpp" -#include "../Containers/FBufferReader.hpp" -#include "../Containers/FBufferWriter.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) { - } - - /** 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; - } - - /** To inc the potential */ - void incPotential(const FReal inPotential) { - this->potential += inPotential; - } - - /** Save current object */ - void save(FBufferWriter& buffer) const { - buffer << potential; - } - /** Retrieve current object */ - void restore(FBufferReader& buffer) { - buffer >> potential; - } -}; - - -#endif //FEXTENDPOTENTIAL_HPP - - diff --git a/Src/Extensions/FExtendVelocity.hpp b/Src/Extensions/FExtendVelocity.hpp deleted file mode 100755 index 52d5f1313..000000000 --- a/Src/Extensions/FExtendVelocity.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== -#ifndef FEXTENDVELOCITY_HPP -#define FEXTENDVELOCITY_HPP - - - -#include "../Utils/FGlobal.hpp" -#include "../Utils/FPoint.hpp" -#include "../Containers/FBufferReader.hpp" -#include "../Containers/FBufferWriter.hpp" - -/** -* @author Berenger Bramas (berenger.bramas@inria.fr) -* @class FExtendVelocity -* Please read the license -* -* This class is an extenssion. -* It proposes a FPoint as a velocity vector. -*/ -class FExtendVelocity { -protected: - FPoint velocity; //< 3D vector stored in a position object - -public: - /** Default constructor */ - FExtendVelocity() { - } - - /** Copy constructor */ - FExtendVelocity(const FExtendVelocity& other) : velocity(other.velocity) { - } - - /** Copy operator */ - FExtendVelocity& operator=(const FExtendVelocity& other) { - this->velocity = other.velocity; - return *this; - } - - /** Return the velocity */ - const FPoint& getVelocity() const { - return this->velocity; - } - - /** Set Velocity */ - void incVelocity(const FPoint& inVelocity) { - this->velocity += inVelocity; - } - - /** Set Velocity with 3 FReals */ - void incVelocity(const FReal inVx, const FReal inVy, const FReal inVz) { - this->velocity.incX(inVx); - this->velocity.incY(inVy); - this->velocity.incZ(inVz); - } - - /** set the velocity from 3 variables */ - void setVelocity(const FReal inVx, const FReal inVy, const FReal inVz) { - this->velocity.setPosition(inVx , inVy, inVz); - } - - /** Save current object */ - void save(FBufferWriter& buffer) const { - buffer << velocity; - } - /** Retrieve current object */ - void restore(FBufferReader& buffer) { - buffer >> velocity; - } -}; - - -#endif //FEXTENDVELOCITY_HPP - - diff --git a/Src/Files/FAbstractLoader.hpp b/Src/Files/FAbstractLoader.hpp index af3a9564f..5f09e6a54 100755 --- a/Src/Files/FAbstractLoader.hpp +++ b/Src/Files/FAbstractLoader.hpp @@ -18,6 +18,8 @@ #include "../Utils/FGlobal.hpp" + + class FPoint; /** @@ -34,7 +36,6 @@ class FPoint; * * @warning Inherite from this class when defining a loader class */ -template <class ParticleClass> class FAbstractLoader { public: /** Default destructor */ @@ -64,24 +65,6 @@ public: * @return true if file is open */ virtual bool isOpen() const = 0; - - /** - * Fill the next particle - * @param inParticle the particle to fill - */ - virtual void fillParticle(ParticleClass& inParticle) = 0; - - /** Fill a tree with all the particle of the current loader - * @param tree the tree to fill - */ - template <class OctreeClass> - void fillTree(OctreeClass& tree){ - ParticleClass particleToFill; - for(int idxPart = 0 ; idxPart < getNumberOfParticles() ; ++idxPart){ - fillParticle(particleToFill); - tree.insert(particleToFill); - } - } }; diff --git a/Src/Files/FBasicLoader.hpp b/Src/Files/FBasicLoader.hpp index a0523c676..437704c12 100755 --- a/Src/Files/FBasicLoader.hpp +++ b/Src/Files/FBasicLoader.hpp @@ -49,8 +49,7 @@ * } <br> * @endcode */ -template <class ParticleClass> -class FBasicLoader : public FAbstractLoader<ParticleClass> { +class FBasicLoader : public FAbstractLoader { protected: std::ifstream file; //< The file to read FPoint centerOfBox; //< The center of box read from file @@ -120,10 +119,10 @@ public: * @warning to work with the loader, particles has to expose a setPosition method * @param the particle to fill */ - void fillParticle(ParticleClass& inParticle){ + void fillParticle(FPoint*const inParticlePosition){ FReal x,y,z; this->file >> x >> y >> z; - inParticle.setPosition(FPoint(x,y,z)); + inParticlePosition->setPosition(x,y,z); } }; diff --git a/Src/Files/FEwalLoader.hpp b/Src/Files/FEwalLoader.hpp index da494e5f0..a67620815 100755 --- a/Src/Files/FEwalLoader.hpp +++ b/Src/Files/FEwalLoader.hpp @@ -26,61 +26,13 @@ #include "../Utils/FPoint.hpp" -template <class BaseClass> -class FEwalParticle : public BaseClass { -public: - // Type of particle - enum Type{ - OW, - HW, - Undefined, - }; - -private: - Type type; //< current type - int index; //< current index in array - int indexInFile; //< current index in array - -public: - // Basic constructor - FEwalParticle() : type(Undefined), index(-1), indexInFile(-1) { - } - - Type getType() const{ - return type; - } - - void setType(const Type inType) { - type = inType; - } - - int getIndex() const{ - return index; - } - - void setIndex( const int inIndex ){ - index = inIndex; - } - - int getIndexInFile() const{ - return indexInFile; - } - - void setIndexInFile( const int inIndex ){ - indexInFile = inIndex; - } -}; - - - /** * @author Berenger Bramas (berenger.bramas@inria.fr) * @class FEwalLoader * Please read the license * Particle has to extend {FExtendPhysicalValue,FExtendPosition} */ -template <class ParticleClass> -class FEwalLoader : public FAbstractLoader<ParticleClass> { +class FEwalLoader : public FAbstractLoader { protected: std::ifstream file; //< The file to read FPoint centerOfBox; //< The center of box read from file @@ -88,6 +40,12 @@ protected: int nbParticles; //< the number of particles read from file int levcfg ; //< DL_POLY CONFIG file key. 0,1 or 2 public: + enum Type{ + OW, + HW, + Undefined, + }; + /** * The constructor need the file name * @param filename the name of the file to open @@ -177,7 +135,7 @@ public: 7.64746800518 -1.34490700206 -2.81036521708 -4406.48579000 6815.52906417 10340.2577024 */ - void fillParticle(ParticleClass& inParticle){ + void fillParticle(FReal inParticle[7], int inIndex [1], Type inType[1]){ FReal x, y, z, fx, fy, fz, vx, vy, vz; int index; char type[2]; @@ -198,28 +156,28 @@ public: file >> fx >> fy >> fz; } - - // std::cout << " x >> y >> z: " << x<< " " <<y<< " " <<z <<std::endl; - inParticle.setPosition(x,y,z); - inParticle.setForces(fx,fy,fz); - //inParticle.setForces(vx,vy,vz); - inParticle.setIndexInFile(index); + inParticle[0] = x; + inParticle[1] = y; + inParticle[2] = z; + inParticle[3] = fx; + inParticle[4] = fy; + inParticle[5] = fz; + inIndex[0] = index; if( strncmp(type, "OW", 2) == 0){ - inParticle.setPhysicalValue(FReal(-0.82)); - inParticle.setType(ParticleClass::OW); + inParticle[6] = FReal(-0.82); + inType[0] = OW; } else{ - inParticle.setPhysicalValue(FReal(0.41)); - inParticle.setType(ParticleClass::HW); + inParticle[6] = FReal(-0.41); + inType[0] = HW; } } }; -template <class ParticleClass> -class FEwalBinLoader : public FAbstractLoader<ParticleClass> { +class FEwalBinLoader : public FAbstractLoader { protected: FILE* const file; //< The file to read FPoint centerOfBox; //< The center of box read from file @@ -324,7 +282,7 @@ public: * @param the particle to fill [index charge x y z fx fy fz] */ - void fillParticle(ParticleClass& inParticle){ + void fillParticle(FPoint* inPosition, FReal inForces[3], FReal* inPhysicalValue, int* inIndex){ double x, y, z, fx, fy, fz, charge; int index; @@ -346,10 +304,12 @@ public: removeWarning = fread(&size, sizeof(int), 1, file); if(size != 60) printf("Error in loader ewal Size %d should be %d\n", size, 60); - inParticle.setPosition(x,y,z); - inParticle.setForces(fx,fy,fz); - inParticle.setIndexInFile(index); - inParticle.setPhysicalValue(charge); + inPosition->setPosition( x, y ,z); + inForces[0] = fx; + inForces[1] = fy; + inForces[2] = fz; + *inPhysicalValue = charge; + *inIndex = index; } }; diff --git a/Src/Files/FFmaBinLoader.hpp b/Src/Files/FFmaBinLoader.hpp index 391d208a5..964fc2184 100755 --- a/Src/Files/FFmaBinLoader.hpp +++ b/Src/Files/FFmaBinLoader.hpp @@ -51,8 +51,7 @@ * * Particle has to extend {FExtendPhysicalValue,FExtendPosition} */ -template <class ParticleClass> -class FFmaBinLoader : public FAbstractLoader<ParticleClass> { +class FFmaBinLoader : public FAbstractLoader { protected: FILE* const file; //< The file to read FPoint centerOfBox; //< The center of box read from file @@ -137,7 +136,7 @@ public: * @warning to work with the loader, particles has to expose a setPosition method * @param the particle to fill */ - void fillParticle(ParticleClass& inParticle){ + void fillParticle(FPoint*const inParticlePosition, FReal*const physicalValue){ FReal x,y,z,data; removeWarning += fread(&x, sizeof(FReal), 1, file); @@ -145,8 +144,8 @@ public: removeWarning += fread(&z, sizeof(FReal), 1, file); removeWarning += fread(&data, sizeof(FReal), 1, file); - inParticle.setPosition(x,y,z); - inParticle.setPhysicalValue(data); + inParticlePosition->setPosition(x,y,z); + (*physicalValue) = data; } }; diff --git a/Src/Files/FFmaLoader.hpp b/Src/Files/FFmaLoader.hpp index b6f289ae8..04dcbcd40 100755 --- a/Src/Files/FFmaLoader.hpp +++ b/Src/Files/FFmaLoader.hpp @@ -51,8 +51,7 @@ * * Particle has to extend {FExtendPhysicalValue,FExtendPosition} */ -template <class ParticleClass> -class FFmaLoader : public FAbstractLoader<ParticleClass> { +class FFmaLoader : public FAbstractLoader { protected: std::ifstream file; //< The file to read FPoint centerOfBox; //< The center of box read from file @@ -123,11 +122,11 @@ public: * @warning to work with the loader, particles has to expose a setPosition method * @param the particle to fill */ - void fillParticle(ParticleClass& inParticle){ + void fillParticle(FPoint*const inParticlePositions, FReal*const inPhysicalValue){ FReal x,y,z,data; this->file >> x >> y >> z >> data; - inParticle.setPosition(x,y,z); - inParticle.setPhysicalValue(data); + inParticlePositions->setPosition(x,y,z); + (*inPhysicalValue) = data; } }; diff --git a/Src/Files/FFmaScanfLoader.hpp b/Src/Files/FFmaScanfLoader.hpp index e585535bc..1d27a2060 100755 --- a/Src/Files/FFmaScanfLoader.hpp +++ b/Src/Files/FFmaScanfLoader.hpp @@ -51,8 +51,7 @@ * * Particle has to extend {FExtendPhysicalValue,FExtendPosition} */ -template <class ParticleClass> -class FFmaScanfLoader : public FAbstractLoader<ParticleClass> { +class FFmaScanfLoader : public FAbstractLoader { protected: FILE* file; //< The file to read FPoint centerOfBox; //< The center of box read from file @@ -130,13 +129,13 @@ public: * @warning to work with the loader, particles has to expose a setPosition method * @param the particle to fill */ - void fillParticle(ParticleClass& inParticle){ + void fillParticle(FPoint*const inParticlePositions, FReal*const inPhysicalValue){ if(this->file){ float x,y,z,data; const int nbReadElements = fscanf(this->file,"%f %f %f %f",&x,&y,&z,&data); if(nbReadElements == 4){ - inParticle.setPosition(x,y,z); - inParticle.setPhysicalValue(data); + inParticlePositions->setPosition(x,y,z); + (*inPhysicalValue) = data; } else{ fclose(this->file); diff --git a/Src/Files/FFmaTsmLoader.hpp b/Src/Files/FFmaTsmLoader.hpp index 84112aee4..e372cdcdc 100755 --- a/Src/Files/FFmaTsmLoader.hpp +++ b/Src/Files/FFmaTsmLoader.hpp @@ -51,8 +51,7 @@ * * Particle has to extend {FExtendPhysicalValue,FExtendPosition} */ -template <class ParticleClass> -class FFmaTsmLoader : public FAbstractLoader<ParticleClass> { +class FFmaTsmLoader : public FAbstractLoader { protected: std::ifstream file; //< The file to read FPoint centerOfBox; //< The center of box read from file @@ -123,14 +122,14 @@ public: * @warning to work with the loader, particles has to expose a setPosition method * @param the particle to fill */ - void fillParticle(ParticleClass& inParticle){ + void fillParticle(FPoint*const inParticlePositions, FReal*const inPhysicalValue, bool*const inIsTarget){ 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(); + + inParticlePositions->setPosition(x,y,z); + *inPhysicalValue = data; + *inIsTarget = isTarget; } }; diff --git a/Src/Files/FHLoader.hpp b/Src/Files/FHLoader.hpp index ff510b583..5695202cb 100755 --- a/Src/Files/FHLoader.hpp +++ b/Src/Files/FHLoader.hpp @@ -51,8 +51,7 @@ * * Particle has to extend {FExtendPhysicalValue,FExtendPosition} */ -template <class ParticleClass> -class FHLoader : public FAbstractLoader<ParticleClass> { +class FHLoader : public FAbstractLoader { protected: FILE* file; //< The file to read FPoint centerOfBox; //< The center of box read from file @@ -134,14 +133,14 @@ public: * @warning to work with the loader, particles has to expose a setPosition method * @param the particle to fill */ - void fillParticle(ParticleClass& inParticle){ + void fillParticle(FPoint*const inParticlePositions, char*const inData){ if(this->file){ char buff[128]; float x,y,z; const int nbReadElements = fscanf(this->file,"%s %f %f %f",buff,&x,&y,&z); if(nbReadElements == 4){ - inParticle.setPosition(x,y,z); - inParticle.setData(buff[0]); + inParticlePositions->setPosition(x,y,z); + (*inData) = buff[0]; } else{ fclose(this->file); diff --git a/Src/Files/FMpiFmaLoader.hpp b/Src/Files/FMpiFmaLoader.hpp index 3afc40d78..849cfa78f 100755 --- a/Src/Files/FMpiFmaLoader.hpp +++ b/Src/Files/FMpiFmaLoader.hpp @@ -52,8 +52,7 @@ * * Particle has to extend {FExtendPhysicalValue,FExtendPosition} */ -template <class ParticleClass> -class FMpiFmaLoader : public FAbstractLoader<ParticleClass> { +class FMpiFmaLoader : public FAbstractLoader { protected: FPoint centerOfBox; //< The center of box read from file FReal boxWidth; //< the box width read from file @@ -226,9 +225,9 @@ public: * @warning to work with the loader, particles has to expose a setPosition method * @param the particle to fill */ - void fillParticle(ParticleClass& inParticle){ - inParticle.setPosition(particles[idxParticles],particles[idxParticles+1],particles[idxParticles+2]); - inParticle.setPhysicalValue(particles[idxParticles+3]); + void fillParticle(FPoint*const inParticlePositions, FReal*const inPhysicalValue){ + inParticlePositions->setPosition(particles[idxParticles],particles[idxParticles+1],particles[idxParticles+2]); + (*inPhysicalValue) = (particles[idxParticles+3]); idxParticles += 4; } diff --git a/Src/Files/FRandomLoader.hpp b/Src/Files/FRandomLoader.hpp index 70f302fdb..21fce59d6 100755 --- a/Src/Files/FRandomLoader.hpp +++ b/Src/Files/FRandomLoader.hpp @@ -31,8 +31,7 @@ * @class FRandomLoader * Please read the license */ -template <class ParticleClass> -class FRandomLoader : public FAbstractLoader<ParticleClass> { +class FRandomLoader : public FAbstractLoader { protected: const size_t nbParticles; //< the number of particles const FReal boxWidth; //< the box width @@ -90,8 +89,8 @@ public: * @warning to work with the loader, particles has to expose a setPosition method * @param the particle to fill */ - void fillParticle(ParticleClass& inParticle){ - inParticle.setPosition( + void fillParticle(FPoint*const inParticlePositions){ + inParticlePositions->setPosition( (getRandom() * boxWidth) + centerOfBox.getX() - boxWidth/2, (getRandom() * boxWidth) + centerOfBox.getY() - boxWidth/2, (getRandom() * boxWidth) + centerOfBox.getZ() - boxWidth/2); @@ -107,18 +106,17 @@ public: /** This class is a random loader but it also generate * randomly the particles type (target or source) */ -template <class ParticleClass> -class FRandomLoaderTsm : public FRandomLoader<ParticleClass> { +class FRandomLoaderTsm : public FRandomLoader { public: FRandomLoaderTsm(const size_t inNbParticles, const FReal inBoxWidth = 1.0, const FPoint& inCenterOfBox = FPoint(0,0,0), const unsigned int inSeed = static_cast<unsigned int>(time(NULL))) - : FRandomLoader<ParticleClass>(inNbParticles,inBoxWidth,inCenterOfBox,inSeed) { + : FRandomLoader(inNbParticles,inBoxWidth,inCenterOfBox,inSeed) { } - void fillParticle(ParticleClass& inParticle){ - FRandomLoader<ParticleClass>::fillParticle(inParticle); - if(FRandomLoader<ParticleClass>::getRandom() > 0.5 ) inParticle.setAsTarget(); - else inParticle.setAsSource(); + + void fillParticle(FPoint*const inParticlePositions, bool*const isTarget){ + FRandomLoader::fillParticle(inParticlePositions); + (*isTarget) = (FRandomLoader::getRandom() > 0.5 ); } }; diff --git a/Src/Files/FTreeCsvSaver.hpp b/Src/Files/FTreeCsvSaver.hpp index e5378176e..b7556760a 100755 --- a/Src/Files/FTreeCsvSaver.hpp +++ b/Src/Files/FTreeCsvSaver.hpp @@ -25,7 +25,7 @@ /** This class is to export a tree in csv file * */ -template <class OctreeClass, class ContainerClass , class ParticleClass> +template <class OctreeClass, class ContainerClass > class FTreeCsvSaver { const bool includeHeader; //< To include a line of header int nbFrames; //< The current frame @@ -66,34 +66,29 @@ public: typename OctreeClass::Iterator octreeIterator(tree); octreeIterator.gotoBottomLeft(); do{ - typename ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListTargets()); - - while( iter.hasNotFinished() ){ - file << iter.data().getPosition().getX() << "," << iter.data().getPosition().getY() << "," << - iter.data().getPosition().getZ() << "," << getValue(&iter.data()) << "\n"; - iter.gotoNext(); + FReal values[4]; + { + const ContainerClass* container = octreeIterator.getCurrentListTargets(); + for(int idxPart = 0 ; idxPart < container->getNbParticles() ; ++idxPart){ + container->fillToCsv(idxPart, values); + file << values[0] << "," << values[1] << "," << + values[2] << "," << values[3] << "\n"; + } } const bool isUsingTsm = (octreeIterator.getCurrentListTargets() != octreeIterator.getCurrentListSrc()); if( isUsingTsm ){ - typename ContainerClass::BasicIterator iterSources(*octreeIterator.getCurrentListSrc()); - - while( iterSources.hasNotFinished() ){ - file << iterSources.data().getPosition().getX() << "," << iterSources.data().getPosition().getY() << "," << - iterSources.data().getPosition().getZ() << "," << getValue(&iterSources.data()) << "\n"; - iterSources.gotoNext(); + const ContainerClass* container = octreeIterator.getCurrentListSrc(); + for(int idxPart = 0 ; idxPart < container->getNbParticles() ; ++idxPart){ + container->fillToCsv(idxPart, values); + file << values[0] << "," << values[1] << "," << + values[2] << "," << values[3] << "\n"; } } } while(octreeIterator.moveRight()); file.close(); } - - /** Inherit from this class and customize this function if you need it - */ - virtual FReal getValue(ParticleClass*const part){ - return FReal(0); - } }; diff --git a/Src/Files/FTreeIO.hpp b/Src/Files/FTreeIO.hpp index 9b04e8a73..39f423325 100755 --- a/Src/Files/FTreeIO.hpp +++ b/Src/Files/FTreeIO.hpp @@ -35,9 +35,16 @@ * ... */ class FTreeIO{ + + enum TargetSourceDiff{ + TsmUndef, + TsmUsed, + TsmUnused + }; + public: /** To save in memory */ - template <class OctreeClass, class CellClass, class ParticleClass , class ContainerClass > + template <class OctreeClass, class CellClass, class LeafClass, class ContainerClass > static bool Save(const char filename[], OctreeClass& tree){ std::ofstream file(filename, std::ofstream::binary | std::ofstream::out ); FBufferWriter buffer; @@ -70,22 +77,16 @@ public: octreeIterator.gotoBottomLeft(); const bool useTargetSource = (octreeIterator.getCurrentListSrc() != octreeIterator.getCurrentListTargets()); if( useTargetSource ){ + TargetSourceDiff tsm = TsmUsed; + file.write((const char*)&tsm,sizeof(tsm)); + do{ - const int nbParticlesInLeaf = (octreeIterator.getCurrentListSrc()->getSize() + octreeIterator.getCurrentListTargets()->getSize()); - file.write((const char*)&nbParticlesInLeaf,sizeof(int)); + const MortonIndex mindex = octreeIterator.getCurrentGlobalIndex(); + file.write((const char*)&mindex,sizeof(mindex)); buffer.reset(); - typename ContainerClass::BasicIterator iterSrc(*octreeIterator.getCurrentListSrc()); - while( iterSrc.hasNotFinished() ){ - iterSrc.data().save(buffer); - iterSrc.gotoNext(); - } - - typename ContainerClass::BasicIterator iterTarget(*octreeIterator.getCurrentListTargets()); - while( iterTarget.hasNotFinished() ){ - iterTarget.data().save(buffer); - iterTarget.gotoNext(); - } + octreeIterator.getCurrentListSrc()->save(buffer); + octreeIterator.getCurrentListTargets()->save(buffer); const int sizeOfLeaf = buffer.getSize(); file.write((const char*) &sizeOfLeaf, sizeof(int)); @@ -95,16 +96,14 @@ public: } while(octreeIterator.moveRight()); } else{ + TargetSourceDiff tsm = TsmUnused; + file.write((const char*)&tsm,sizeof(tsm)); do{ - const int nbParticlesInLeaf = octreeIterator.getCurrentListSrc()->getSize(); - file.write((const char*)&nbParticlesInLeaf,sizeof(int)); + const MortonIndex mindex = octreeIterator.getCurrentGlobalIndex(); + file.write((const char*)&mindex,sizeof(mindex)); buffer.reset(); - typename ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListSrc()); - while( iter.hasNotFinished() ){ - iter.data().save(buffer); - iter.gotoNext(); - } + octreeIterator.getCurrentListSrc()->save(buffer); const int sizeOfLeaf = buffer.getSize(); file.write((const char*) &sizeOfLeaf, sizeof(int)); @@ -163,7 +162,7 @@ public: /** To load from memory */ - template <class OctreeClass, class CellClass, class ParticleClass , class ContainerClass > + template <class OctreeClass, class CellClass, class LeafClass, class ContainerClass > static bool Load(const char filename[], OctreeClass& tree){ std::ifstream file(filename, std::ifstream::binary | std::ifstream::in ); FBufferReader buffer; @@ -196,11 +195,12 @@ public: int nbLeaf = 0; file.read((char*)&nbLeaf, sizeof(int)); - ParticleClass particle; + TargetSourceDiff tsm = TsmUndef; + file.read((char*)&tsm,sizeof(tsm)); for(int idxLeaf = 0 ; idxLeaf < nbLeaf ; ++idxLeaf){ - int particlesInLeaf = 0; - file.read((char*)&particlesInLeaf, sizeof(int)); + MortonIndex mindex = 0; + file.read((char*)&mindex, sizeof(mindex)); int sizeOfLeaf = 0; file.read((char*)&sizeOfLeaf, sizeof(int)); @@ -208,9 +208,11 @@ public: buffer.reserve(sizeOfLeaf); file.read((char*)buffer.data(), sizeOfLeaf); - for(int idxParticle = 0 ; idxParticle < particlesInLeaf ; ++idxParticle){ - particle.restore(buffer); - tree.insert(particle); + LeafClass*const leaf = tree.createLeaf(mindex); + leaf->getSrc()->restore(buffer); + + if( tsm == TsmUsed ){ + leaf->getTargets()->restore(buffer); } } } diff --git a/Src/Kernels/Chebyshev/FAbstractChebKernel.hpp b/Src/Kernels/Chebyshev/FAbstractChebKernel.hpp index 648f044a6..43c2f00af 100755 --- a/Src/Kernels/Chebyshev/FAbstractChebKernel.hpp +++ b/Src/Kernels/Chebyshev/FAbstractChebKernel.hpp @@ -22,6 +22,8 @@ #include "../../Components/FAbstractKernels.hpp" +#include "../P2P/FP2P.hpp" + #include "./FChebInterpolator.hpp" class FTreeCoordinate; @@ -35,14 +37,13 @@ template <KERNEL_FUNCCTION_IDENTIFIER Identifier> struct DirectInteactionCompute * implements all interfaces (P2P, P2M, M2M, M2L, L2L, L2P) which are required by * the FFmmAlgorithm and FFmmAlgorithmThread. * - * @tparam ParticleClass Type of particle * @tparam CellClass Type of cell * @tparam ContainerClass Type of container to store particles * @tparam MatrixKernelClass Type of matrix kernel function * @tparam ORDER Chebyshev interpolation order */ -template <class ParticleClass, class CellClass, class ContainerClass, class MatrixKernelClass, int ORDER> -class FAbstractChebKernel : public FAbstractKernels<ParticleClass, CellClass, ContainerClass> +template < class CellClass, class ContainerClass, class MatrixKernelClass, int ORDER> +class FAbstractChebKernel : public FAbstractKernels< CellClass, ContainerClass> { protected: enum {nnodes = TensorTraits<ORDER>::nnodes}; @@ -127,86 +128,11 @@ public: void P2P(const FTreeCoordinate& /* LeafCellCoordinate */, // needed for periodic boundary conditions ContainerClass* const FRestrict TargetParticles, - const ContainerClass* const FRestrict SourceParticles, + const ContainerClass* const FRestrict /*SourceParticles*/, ContainerClass* const NeighborSourceParticles[27], const int /* size */) { - // loop: target particles - typename ContainerClass::BasicIterator iTargets(*TargetParticles); - - if (TargetParticles != SourceParticles) { - - while (iTargets.hasNotFinished()) { - ParticleClass& Target = iTargets.data(); - - { // loop: source particles (target leaf cell == source leaf cell) - typename ContainerClass::ConstBasicIterator iSources(*SourceParticles); - while (iSources.hasNotFinished()) { - const ParticleClass& Source = iSources.data(); - // only if target and source are not identical - DirectInteactionComputer<MatrixKernelClass::Identifier>::compute(Target, Source); - // progress sources - iSources.gotoNext(); - } - } - - { // loop: source particles (target leaf cell != source leaf cell) - for (unsigned int idx=0; idx<27; ++idx) { - if (NeighborSourceParticles[idx]) { - typename ContainerClass::ConstBasicIterator iSources(*NeighborSourceParticles[idx]); - while (iSources.hasNotFinished()) { - const ParticleClass& Source = iSources.data(); - // target and source cannot be identical - DirectInteactionComputer<MatrixKernelClass::Identifier>::compute(Target, Source); - // progress sources - iSources.gotoNext(); - } - } - } - } - - // progress targets - iTargets.gotoNext(); - } - - } else { - - while (iTargets.hasNotFinished()) { - ParticleClass& Target = iTargets.data(); - - { // loop: source particles (target leaf cell == source leaf cell) - typename ContainerClass::BasicIterator iSources = iTargets; - iSources.gotoNext(); - while (iSources.hasNotFinished()) { - ParticleClass& Source = iSources.data(); - // only if target and source are not identical - DirectInteactionComputer<MatrixKernelClass::Identifier>::computeMutual(Target, Source); - // progress sources - iSources.gotoNext(); - } - } - - { // loop: source particles (target leaf cell != source leaf cell) - for (unsigned int idx=0; idx<=13; ++idx) { - if (NeighborSourceParticles[idx]) { - typename ContainerClass::BasicIterator iSources(*NeighborSourceParticles[idx]); - while (iSources.hasNotFinished()) { - ParticleClass& Source = iSources.data(); - // target and source cannot be identical - DirectInteactionComputer<MatrixKernelClass::Identifier>::computeMutual(Target, Source); - // progress sources - iSources.gotoNext(); - } - } - } - } - - // progress targets - iTargets.gotoNext(); - } - - } - + DirectInteactionComputer<MatrixKernelClass::Identifier>::P2P(TargetParticles,NeighborSourceParticles); } }; @@ -216,43 +142,11 @@ public: template <> struct DirectInteactionComputer<ONE_OVER_R> { - template <typename ParticleClass> - static void compute(ParticleClass& Target, const ParticleClass& Source) // 34 overall flops - { - FPoint xy(Source.getPosition() - Target.getPosition()); // 3 flops - const FReal one_over_r = FReal(1.) / FMath::Sqrt(xy.getX()*xy.getX() + - xy.getY()*xy.getY() + - xy.getZ()*xy.getZ()); // 1 + 15 + 5 = 21 flops - const FReal wt = Target.getPhysicalValue(); - const FReal ws = Source.getPhysicalValue(); - - // laplace potential - Target.incPotential(one_over_r * ws); // 2 flops - - // force - xy *= ((ws*wt) * (one_over_r*one_over_r*one_over_r)); // 5 flops - Target.incForces(xy.getX(), xy.getY(), xy.getZ()); // 3 flops - } - - template <typename ParticleClass> - static void computeMutual(ParticleClass& Target, ParticleClass& Source) // 39 overall flops - { - FPoint xy(Source.getPosition() - Target.getPosition()); // 3 flops - const FReal one_over_r = FReal(1.) / FMath::Sqrt(xy.getX()*xy.getX() + - xy.getY()*xy.getY() + - xy.getZ()*xy.getZ()); // 1 + 15 + 5 = 21 flops - const FReal wt = Target.getPhysicalValue(); - const FReal ws = Source.getPhysicalValue(); - - // laplace potential - Target.incPotential(one_over_r * ws); // 2 flops - Source.incPotential(one_over_r * wt); // 2 flops - - // force - xy *= ((ws*wt) * (one_over_r*one_over_r*one_over_r)); // 5 flops - Target.incForces( xy.getX(), xy.getY(), xy.getZ()); // 3 flops - Source.incForces((-xy.getX()), (-xy.getY()), (-xy.getZ())); // 3 flops - } + template <typename ContainerClass> + static void P2P( ContainerClass* const FRestrict TargetParticles, + ContainerClass* const NeighborSourceParticles[27]){ + FP2P::FullMutual(TargetParticles,NeighborSourceParticles,14); + } }; @@ -260,49 +154,11 @@ struct DirectInteactionComputer<ONE_OVER_R> template <> struct DirectInteactionComputer<LEONARD_JONES_POTENTIAL> { - template <typename ParticleClass> - static void compute(ParticleClass& Target, const ParticleClass& Source) // 39 overall flops - { - FPoint xy(Source.getPosition() - Target.getPosition()); // 3 flops - const FReal one_over_r = FReal(1.) / FMath::Sqrt(xy.getX()*xy.getX() + - xy.getY()*xy.getY() + - xy.getZ()*xy.getZ()); // 1 + 15 + 5 = 21 flops - const FReal wt = Target.getPhysicalValue(); - const FReal ws = Source.getPhysicalValue(); - - // lenard-jones potential - const FReal one_over_r3 = one_over_r * one_over_r * one_over_r; - const FReal one_over_r6 = one_over_r3 * one_over_r3; - Target.incPotential((one_over_r6*one_over_r6 - one_over_r6) * ws); // 2 flops - - // force - const FReal one_over_r4 = one_over_r3 * one_over_r; // 1 flop - xy *= ((ws*wt) * (FReal(12.)*one_over_r6*one_over_r4*one_over_r4 - FReal(6.)*one_over_r4*one_over_r4)); // 9 flops - Target.incForces(xy.getX(), xy.getY(), xy.getZ()); // 3 flops - } - - template <typename ParticleClass> - static void computeMutual(ParticleClass& Target, ParticleClass& Source) // 44 overall flops - { - FPoint xy(Source.getPosition() - Target.getPosition()); // 3 flops - const FReal one_over_r = FReal(1.) / FMath::Sqrt(xy.getX()*xy.getX() + - xy.getY()*xy.getY() + - xy.getZ()*xy.getZ()); // 1 + 15 + 5 = 21 flops - const FReal wt = Target.getPhysicalValue(); - const FReal ws = Source.getPhysicalValue(); - - // lenard-jones potential - const FReal one_over_r3 = one_over_r * one_over_r * one_over_r; - const FReal one_over_r6 = one_over_r3 * one_over_r3; - Target.incPotential((one_over_r6*one_over_r6 - one_over_r6) * ws); // 2 flops - Source.incPotential((one_over_r6*one_over_r6 - one_over_r6) * wt); // 2 flops - - // force - const FReal one_over_r4 = one_over_r3 * one_over_r; // 1 flop - xy *= ((ws*wt) * (FReal(12.)*one_over_r6*one_over_r4*one_over_r4 - FReal(6.)*one_over_r4*one_over_r4)); // 9 flops - Target.incForces( xy.getX(), xy.getY(), xy.getZ()); // 3 flops - Source.incForces((-xy.getX()), (-xy.getY()), (-xy.getZ())); // 3 flops - } + template <typename ContainerClass> + static void P2P( ContainerClass* const FRestrict TargetParticles, + ContainerClass* const NeighborSourceParticles[27]){ + FP2P::FullMutualLJ(TargetParticles,NeighborSourceParticles,14); + } }; diff --git a/Src/Kernels/Chebyshev/FChebFlopsSymKernel.hpp b/Src/Kernels/Chebyshev/FChebFlopsSymKernel.hpp index 51728d129..58dc8d545 100755 --- a/Src/Kernels/Chebyshev/FChebFlopsSymKernel.hpp +++ b/Src/Kernels/Chebyshev/FChebFlopsSymKernel.hpp @@ -16,6 +16,8 @@ #ifndef FCHEBFLOPSSYMKERNEL_HPP #define FCHEBFLOPSSYMKERNEL_HPP +#include <stdexcept> + #include "../../Utils/FGlobal.hpp" #include "../../Utils/FTrace.hpp" #include "../../Utils/FSmartPointer.hpp" @@ -40,15 +42,14 @@ class FTreeCoordinate; * (P2P, P2M, M2M, M2L, L2L, L2P) which are required by the FFmmAlgorithm and * FFmmAlgorithmThread. * - * @tparam ParticleClass Type of particle * @tparam CellClass Type of cell * @tparam ContainerClass Type of container to store particles * @tparam MatrixKernelClass Type of matrix kernel function * @tparam ORDER Chebyshev interpolation order */ -template <class ParticleClass, class CellClass, class ContainerClass, class MatrixKernelClass, int ORDER> +template < class CellClass, class ContainerClass, class MatrixKernelClass, int ORDER> class FChebFlopsSymKernel - : public FAbstractKernels<ParticleClass, CellClass, ContainerClass> + : public FAbstractKernels<CellClass, ContainerClass> { enum {nnodes = TensorTraits<ORDER>::nnodes}; public: @@ -176,7 +177,7 @@ public: void P2M(CellClass* const /* not needed */, const ContainerClass* const SourceParticles) { - flopsP2M += countFlopsP2M(SourceParticles->getSize()); + flopsP2M += countFlopsP2M(SourceParticles->getNbParticles()); } @@ -231,14 +232,14 @@ public: ContainerClass* const TargetParticles) { //// 1.a) apply Sx - //flopsL2P += countFlopsP2MorL2P(TargetParticlesParticles->getSize()) + TargetParticles->getSize(); + //flopsL2P += countFlopsP2MorL2P(TargetParticlesParticles->getNbParticles()) + TargetParticles->getNbParticles(); //// 1.b) apply Px (grad Sx) - //flopsL2P += countFlopsL2PGradient(TargetParticlesParticles->getSize()) + 3 * TargetParticles->getSize(); + //flopsL2P += countFlopsL2PGradient(TargetParticlesParticles->getNbParticles()) + 3 * TargetParticles->getNbParticles(); // or // 2) apply Sx and Px (grad Sx) - flopsL2P += countFlopsL2PTotal(TargetParticles->getSize()) + 4 * TargetParticles->getSize(); + flopsL2P += countFlopsL2PTotal(TargetParticles->getNbParticles()) + 4 * TargetParticles->getNbParticles(); } @@ -250,15 +251,15 @@ public: const int /* size */) { if (TargetParticles != SourceParticles) { - flopsP2P += countFlopsP2P() * TargetParticles->getSize() * SourceParticles->getSize(); + flopsP2P += countFlopsP2P() * TargetParticles->getNbParticles() * SourceParticles->getNbParticles(); for (unsigned int idx=0; idx<27; ++idx) if (NeighborSourceParticles[idx]) - flopsP2P += countFlopsP2P() * TargetParticles->getSize() * NeighborSourceParticles[idx]->getSize(); + flopsP2P += countFlopsP2P() * TargetParticles->getNbParticles() * NeighborSourceParticles[idx]->getNbParticles(); } else { - flopsP2P += countFlopsP2Pmutual() * ((TargetParticles->getSize()*TargetParticles->getSize()+TargetParticles->getSize()) / 2); + flopsP2P += countFlopsP2Pmutual() * ((TargetParticles->getNbParticles()*TargetParticles->getNbParticles()+TargetParticles->getNbParticles()) / 2); for (unsigned int idx=0; idx<=13; ++idx) if (NeighborSourceParticles[idx]) - flopsP2P += countFlopsP2Pmutual() * TargetParticles->getSize() * NeighborSourceParticles[idx]->getSize(); + flopsP2P += countFlopsP2Pmutual() * TargetParticles->getNbParticles() * NeighborSourceParticles[idx]->getNbParticles(); } } @@ -278,12 +279,11 @@ public: * Handler to deal with all symmetries: Stores permutation indices and vectors * to reduce 343 different interactions to 16 only. */ -template <class ParticleClass, - class CellClass, +template < class CellClass, class ContainerClass, class MatrixKernelClass, int ORDER> -struct FChebFlopsSymKernel<ParticleClass, CellClass, ContainerClass, MatrixKernelClass, ORDER> +struct FChebFlopsSymKernel<CellClass, ContainerClass, MatrixKernelClass, ORDER> ::SymmetryHandler { // M2L operators @@ -307,7 +307,7 @@ struct FChebFlopsSymKernel<ParticleClass, CellClass, ContainerClass, MatrixKerne nrm2k += singular_values[k-1] * singular_values[k-1]; if (nrm2k > eps*eps * nrm2) return k; } - throw std::runtime_error("rank cannot be larger than nnodes"); + throw std::runtime_error("rank cannot be larger than nnodes"); return 0; } diff --git a/Src/Kernels/Chebyshev/FChebInterpolator.hpp b/Src/Kernels/Chebyshev/FChebInterpolator.hpp index f2fdda49b..0284f2519 100755 --- a/Src/Kernels/Chebyshev/FChebInterpolator.hpp +++ b/Src/Kernels/Chebyshev/FChebInterpolator.hpp @@ -567,9 +567,9 @@ public: template <int ORDER> template <class ContainerClass> inline void FChebInterpolator<ORDER>::applyP2M(const FPoint& center, - const FReal width, - FReal *const multipoleExpansion, - const ContainerClass *const sourceParticles) const + const FReal width, + FReal *const multipoleExpansion, + const ContainerClass *const inParticles) const { // set all multipole expansions to zero FBlas::setzero(nnodes, multipoleExpansion); @@ -587,11 +587,13 @@ inline void FChebInterpolator<ORDER>::applyP2M(const FPoint& center, for(unsigned int i=0; i<(ORDER-1)*(ORDER-1)*(ORDER-1); ++i) W8[i] = FReal(0.); // loop over source particles - typename ContainerClass::ConstBasicIterator iter(*sourceParticles); - while(iter.hasNotFinished()){ - + const FReal*const physicalValues = inParticles->getPhysicalValues(); + const FReal*const positionsX = inParticles->getPositions()[0]; + const FReal*const positionsY = inParticles->getPositions()[1]; + const FReal*const positionsZ = inParticles->getPositions()[2]; + for(int idxPart = 0 ; idxPart < inParticles->getNbParticles() ; ++idxPart){ // map global position to [-1,1] - map(iter.data().getPosition(), localPosition); // 15 flops + map(FPoint(positionsX[idxPart],positionsY[idxPart],positionsZ[idxPart]), localPosition); // 15 flops FReal T_of_x[3][ORDER]; T_of_x[0][0] = FReal(1.); T_of_x[0][1] = localPosition.getX(); @@ -606,7 +608,7 @@ inline void FChebInterpolator<ORDER>::applyP2M(const FPoint& center, T_of_x[2][j] = z2 * T_of_x[2][j-1] - T_of_x[2][j-2]; // 2 flops } - const FReal weight = iter.data().getPhysicalValue(); + const FReal weight = physicalValues[idxPart]; W1 += weight; // 1 flop for (unsigned int i=1; i<ORDER; ++i) { const FReal wx = weight * T_of_x[0][i]; // 1 flop @@ -628,10 +630,7 @@ inline void FChebInterpolator<ORDER>::applyP2M(const FPoint& center, } // flops: (ORDER-1) * 2 } // flops: (ORDER-1) * (6 + (ORDER-1) * 2) } // flops: (ORDER-1) * (6 + (ORDER-1) * (6 + (ORDER-1) * 2)) - - - // increment source iterator - iter.gotoNext(); + } // flops: N * (18 + (ORDER-2) * 6 + (ORDER-1) * (6 + (ORDER-1) * (6 + (ORDER-1) * 2))) //////////////////////////////////////////////////////////////////// @@ -758,9 +757,9 @@ inline void FChebInterpolator<ORDER>::applyP2M(const FPoint& center, template <int ORDER> template <class ContainerClass> inline void FChebInterpolator<ORDER>::applyL2P(const FPoint& center, - const FReal width, - const FReal *const localExpansion, - ContainerClass *const localParticles) const + const FReal width, + const FReal *const localExpansion, + ContainerClass *const inParticles) const { FReal f1; FReal W2[3][ ORDER-1]; @@ -807,11 +806,20 @@ inline void FChebInterpolator<ORDER>::applyL2P(const FPoint& center, // loop over particles const map_glob_loc map(center, width); FPoint localPosition; - typename ContainerClass::BasicIterator iter(*localParticles); - while(iter.hasNotFinished()){ + + //const FReal*const physicalValues = inParticles->getPhysicalValues(); + const FReal*const positionsX = inParticles->getPositions()[0]; + const FReal*const positionsY = inParticles->getPositions()[1]; + const FReal*const positionsZ = inParticles->getPositions()[2]; + //FReal*const forcesX = inParticles->getForcesX(); + //FReal*const forcesY = inParticles->getForcesY(); + //FReal*const forcesZ = inParticles->getForcesZ(); + FReal*const potentials = inParticles->getPotentials(); + + for(int idxPart = 0 ; idxPart < inParticles->getNbParticles() ; ++ idxPart){ // map global position to [-1,1] - map(iter.data().getPosition(), localPosition); // 15 flops + map(FPoint(positionsX[idxPart],positionsY[idxPart],positionsZ[idxPart]), localPosition); // 15 flops FReal T_of_x[3][ORDER]; { @@ -829,7 +837,7 @@ inline void FChebInterpolator<ORDER>::applyL2P(const FPoint& center, } // interpolate and increment target value - FReal targetValue = iter.data().getPotential(); + FReal targetValue = potentials[idxPart]; { FReal f2, f4, f8; { @@ -856,10 +864,7 @@ inline void FChebInterpolator<ORDER>::applyL2P(const FPoint& center, } // 7 + ORDER * (ORDER * (9 + ORDER * 4)) flops // set potential - iter.data().setPotential(targetValue); - - // increment target iterator - iter.gotoNext(); + potentials[idxPart] += (targetValue); } // N * (7 + ORDER * (ORDER * (9 + ORDER * 4))) flops } @@ -959,9 +964,9 @@ inline void FChebInterpolator<ORDER>::applyL2P(const FPoint& center, template <int ORDER> template <class ContainerClass> inline void FChebInterpolator<ORDER>::applyL2PGradient(const FPoint& center, - const FReal width, - const FReal *const localExpansion, - ContainerClass *const localParticles) const + const FReal width, + const FReal *const localExpansion, + ContainerClass *const inParticles) const { //////////////////////////////////////////////////////////////////// // TENSOR-PRODUCT INTERPOLUTION NOT IMPLEMENTED YET HERE!!! //////// @@ -977,11 +982,19 @@ inline void FChebInterpolator<ORDER>::applyL2PGradient(const FPoint& center, FReal U_of_x[ORDER][3]; FReal P[3]; - typename ContainerClass::BasicIterator iter(*localParticles); - while(iter.hasNotFinished()){ + const FReal*const physicalValues = inParticles->getPhysicalValues(); + const FReal*const positionsX = inParticles->getPositions()[0]; + const FReal*const positionsY = inParticles->getPositions()[1]; + const FReal*const positionsZ = inParticles->getPositions()[2]; + FReal*const forcesX = inParticles->getForcesX(); + FReal*const forcesY = inParticles->getForcesY(); + FReal*const forcesZ = inParticles->getForcesZ(); + //FReal*const potentials = inParticles->getPotentials(); + + for(int idxPart = 0 ; idxPart < inParticles->getNbParticles() ; ++ idxPart){ // map global position to [-1,1] - map(iter.data().getPosition(), localPosition); + map(FPoint(positionsX[idxPart],positionsY[idxPart],positionsZ[idxPart]), localPosition); // evaluate chebyshev polynomials of source particle // T_0(x_i) and T_1(x_i) @@ -1066,12 +1079,9 @@ inline void FChebInterpolator<ORDER>::applyL2PGradient(const FPoint& center, forces[2] *= jacobian[2] / nnodes; // set computed forces - iter.data().incForces(forces[0] * iter.data().getPhysicalValue(), - forces[1] * iter.data().getPhysicalValue(), - forces[2] * iter.data().getPhysicalValue()); - - // increment iterator - iter.gotoNext(); + forcesX[idxPart] += forces[0] * physicalValues[idxPart]; + forcesY[idxPart] += forces[1] * physicalValues[idxPart]; + forcesZ[idxPart] += forces[2] * physicalValues[idxPart]; } } @@ -1083,9 +1093,9 @@ inline void FChebInterpolator<ORDER>::applyL2PGradient(const FPoint& center, template <int ORDER> template <class ContainerClass> inline void FChebInterpolator<ORDER>::applyL2PTotal(const FPoint& center, - const FReal width, - const FReal *const localExpansion, - ContainerClass *const localParticles) const + const FReal width, + const FReal *const localExpansion, + ContainerClass *const inParticles) const { FReal f1; FReal W2[3][ ORDER-1]; @@ -1196,11 +1206,19 @@ inline void FChebInterpolator<ORDER>::applyL2PTotal(const FPoint& center, const FReal jacobian[3] = {Jacobian.getX(), Jacobian.getY(), Jacobian.getZ()}; FPoint localPosition; - typename ContainerClass::BasicIterator iter(*localParticles); - while(iter.hasNotFinished()){ + const FReal*const physicalValues = inParticles->getPhysicalValues(); + const FReal*const positionsX = inParticles->getPositions()[0]; + const FReal*const positionsY = inParticles->getPositions()[1]; + const FReal*const positionsZ = inParticles->getPositions()[2]; + FReal*const forcesX = inParticles->getForcesX(); + FReal*const forcesY = inParticles->getForcesY(); + FReal*const forcesZ = inParticles->getForcesZ(); + FReal*const potentials = inParticles->getPotentials(); + + for(int idxPart = 0 ; idxPart < inParticles->getNbParticles() ; ++ idxPart){ // map global position to [-1,1] - map(iter.data().getPosition(), localPosition); // 15 flops + map(FPoint(positionsX[idxPart],positionsY[idxPart],positionsZ[idxPart]), localPosition); // 15 flops FReal U_of_x[3][ORDER]; FReal T_of_x[3][ORDER]; @@ -1270,15 +1288,13 @@ inline void FChebInterpolator<ORDER>::applyL2PTotal(const FPoint& center, } // 28 + (ORDER-1) * ((ORDER-1) * (27 + (ORDER-1) * 16)) flops // set computed potential - iter.data().incPotential(potential); // 1 flop + potentials[idxPart] += (potential); // 1 flop // set computed forces - iter.data().incForces(forces[0] * iter.data().getPhysicalValue(), - forces[1] * iter.data().getPhysicalValue(), - forces[2] * iter.data().getPhysicalValue()); // 6 flops + forcesX[idxPart] += forces[0] * physicalValues[idxPart]; + forcesY[idxPart] += forces[1] * physicalValues[idxPart]; + forcesZ[idxPart] += forces[2] * physicalValues[idxPart]; // 6 flops - // increment target iterator - iter.gotoNext(); } // N * (38 + (ORDER-2)*15 + (ORDER-1)*((ORDER-1) * (27 + (ORDER-1) * 16))) + 6 flops } diff --git a/Src/Kernels/Chebyshev/FChebKernel.hpp b/Src/Kernels/Chebyshev/FChebKernel.hpp index 9e38bbbaa..62a984600 100755 --- a/Src/Kernels/Chebyshev/FChebKernel.hpp +++ b/Src/Kernels/Chebyshev/FChebKernel.hpp @@ -35,21 +35,20 @@ class FTreeCoordinate; * implements all interfaces (P2P, P2M, M2M, M2L, L2L, L2P) which are required by * the FFmmAlgorithm and FFmmAlgorithmThread. * - * @tparam ParticleClass Type of particle * @tparam CellClass Type of cell * @tparam ContainerClass Type of container to store particles * @tparam MatrixKernelClass Type of matrix kernel function * @tparam ORDER Chebyshev interpolation order */ -template <class ParticleClass, class CellClass, class ContainerClass, class MatrixKernelClass, int ORDER> +template < class CellClass, class ContainerClass, class MatrixKernelClass, int ORDER> class FChebKernel - : public FAbstractChebKernel<ParticleClass, CellClass, ContainerClass, MatrixKernelClass, ORDER> + : public FAbstractChebKernel< CellClass, ContainerClass, MatrixKernelClass, ORDER> { // private types typedef FChebM2LHandler<ORDER,MatrixKernelClass> M2LHandlerClass; // using from - typedef FAbstractChebKernel<ParticleClass, CellClass, ContainerClass, MatrixKernelClass, ORDER> + typedef FAbstractChebKernel< CellClass, ContainerClass, MatrixKernelClass, ORDER> AbstractBaseClass; /// Needed for M2L operator @@ -65,7 +64,7 @@ public: const FPoint& inBoxCenter, const FReal inBoxWidth, const FReal Epsilon) - : FAbstractChebKernel<ParticleClass, CellClass, ContainerClass, MatrixKernelClass, ORDER>(inTreeHeight, + : FAbstractChebKernel< CellClass, ContainerClass, MatrixKernelClass, ORDER>(inTreeHeight, inBoxCenter, inBoxWidth), M2LHandler(new M2LHandlerClass(Epsilon)) diff --git a/Src/Kernels/Chebyshev/FChebParticle.hpp b/Src/Kernels/Chebyshev/FChebParticle.hpp deleted file mode 100755 index 7bf207b16..000000000 --- a/Src/Kernels/Chebyshev/FChebParticle.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== -#ifndef FCHEBPARTICLE_HPP -#define FCHEBPARTICLE_HPP - -#include <stdexcept> -#include <cassert> - -#include "../../Extensions/FExtendPosition.hpp" -#include "../../Extensions/FExtendPhysicalValue.hpp" -#include "../../Extensions/FExtendPotential.hpp" -#include "../../Extensions/FExtendForces.hpp" - -/** - * @author Matthias Messner (matthias.matthias@inria.fr) - * @class FChebParticle - * Please read the license - * - * The class @p FChebParticle defines the particle used for the Chebyshev FMM - * approach. - */ -class FChebParticle : public FExtendPosition, - public FExtendPhysicalValue, - public FExtendPotential, - public FExtendForces -{ -public: - ~FChebParticle() {} -}; - - -#endif diff --git a/Src/Kernels/Chebyshev/FChebSymKernel.hpp b/Src/Kernels/Chebyshev/FChebSymKernel.hpp index 79fbb18db..5a63badea 100755 --- a/Src/Kernels/Chebyshev/FChebSymKernel.hpp +++ b/Src/Kernels/Chebyshev/FChebSymKernel.hpp @@ -45,17 +45,16 @@ class FTreeCoordinate; * (P2P, P2M, M2M, M2L, L2L, L2P) which are required by the FFmmAlgorithm and * FFmmAlgorithmThread. * - * @tparam ParticleClass Type of particle * @tparam CellClass Type of cell * @tparam ContainerClass Type of container to store particles * @tparam MatrixKernelClass Type of matrix kernel function * @tparam ORDER Chebyshev interpolation order */ -template <class ParticleClass, class CellClass, class ContainerClass, class MatrixKernelClass, int ORDER> +template < class CellClass, class ContainerClass, class MatrixKernelClass, int ORDER> class FChebSymKernel - : public FAbstractChebKernel<ParticleClass, CellClass, ContainerClass, MatrixKernelClass, ORDER> + : public FAbstractChebKernel<CellClass, ContainerClass, MatrixKernelClass, ORDER> { - typedef FAbstractChebKernel<ParticleClass, CellClass, ContainerClass, MatrixKernelClass, ORDER> AbstractBaseClass; + typedef FAbstractChebKernel<CellClass, ContainerClass, MatrixKernelClass, ORDER> AbstractBaseClass; typedef SymmetryHandler<ORDER, MatrixKernelClass::Type> SymmetryHandlerClass; enum {nnodes = AbstractBaseClass::nnodes}; diff --git a/Src/Kernels/P2P/FP2P.hpp b/Src/Kernels/P2P/FP2P.hpp new file mode 100644 index 000000000..59f6bb38b --- /dev/null +++ b/Src/Kernels/P2P/FP2P.hpp @@ -0,0 +1,469 @@ +#ifndef FP2P_HPP +#define FP2P_HPP + +#include "../../Utils/FGlobal.hpp" + +/** + * @brief The FP2P class + */ +class FP2P { +public: + /** + * + */ + template <class ContainerClass> + static void FullMutual(ContainerClass* const FRestrict inTargets, ContainerClass* const inNeighbors[], + const int limiteNeighbors){ + + const int nbParticlesTargets = inTargets->getNbParticles(); + const FReal*const targetsPhysicalValues = inTargets->getPhysicalValues(); + const FReal*const targetsX = inTargets->getPositions()[0]; + const FReal*const targetsY = inTargets->getPositions()[1]; + const FReal*const targetsZ = inTargets->getPositions()[2]; + FReal*const targetsForcesX = inTargets->getForcesX(); + FReal*const targetsForcesY = inTargets->getForcesY(); + FReal*const targetsForcesZ = inTargets->getForcesZ(); + FReal*const targetsPotentials = inTargets->getPotentials(); + + for(int idxNeighbors = 0 ; idxNeighbors < limiteNeighbors ; ++idxNeighbors){ + for(int idxTarget = 0 ; idxTarget < nbParticlesTargets ; ++idxTarget){ + if( inNeighbors[idxNeighbors] ){ + const int nbParticlesSources = inNeighbors[idxNeighbors]->getNbParticles(); + const FReal*const sourcesPhysicalValues = inNeighbors[idxNeighbors]->getPhysicalValues(); + const FReal*const sourcesX = inNeighbors[idxNeighbors]->getPositions()[0]; + const FReal*const sourcesY = inNeighbors[idxNeighbors]->getPositions()[1]; + const FReal*const sourcesZ = inNeighbors[idxNeighbors]->getPositions()[2]; + FReal*const sourcesForcesX = inNeighbors[idxNeighbors]->getForcesX(); + FReal*const sourcesForcesY = inNeighbors[idxNeighbors]->getForcesY(); + FReal*const sourcesForcesZ = inNeighbors[idxNeighbors]->getForcesZ(); + FReal*const sourcesPotentials = inNeighbors[idxNeighbors]->getPotentials(); + + for(int idxSource = 0 ; idxSource < nbParticlesSources ; ++idxSource){ + double dx = sourcesX[idxSource] - targetsX[idxTarget]; + double dy = sourcesY[idxSource] - targetsY[idxTarget]; + double dz = sourcesZ[idxSource] - targetsZ[idxTarget]; + + double inv_square_distance = 1.0 / (dx*dx + dy*dy + dz*dz); + const double inv_distance = sqrt(inv_square_distance); + + inv_square_distance *= inv_distance; + inv_square_distance *= targetsPhysicalValues[idxTarget] * sourcesPhysicalValues[idxSource]; + + dx *= inv_square_distance; + dy *= inv_square_distance; + dz *= inv_square_distance; + + targetsForcesX[idxTarget] += dx; + targetsForcesY[idxTarget] += dy; + targetsForcesZ[idxTarget] += dz; + targetsPotentials[idxTarget] += inv_distance * sourcesPhysicalValues[idxSource]; + + sourcesForcesX[idxSource] -= dx; + sourcesForcesY[idxSource] -= dy; + sourcesForcesZ[idxSource] -= dz; + sourcesPotentials[idxSource] += inv_distance * targetsPhysicalValues[idxTarget]; + } + } + } + } + + for(int idxTarget = 0 ; idxTarget < nbParticlesTargets ; ++idxTarget){ + for(int idxSource = idxTarget + 1 ; idxSource < nbParticlesTargets ; ++idxSource){ + double dx = targetsX[idxSource] - targetsX[idxTarget]; + double dy = targetsY[idxSource] - targetsY[idxTarget]; + double dz = targetsZ[idxSource] - targetsZ[idxTarget]; + + double inv_square_distance = 1.0 / (dx*dx + dy*dy + dz*dz); + const double inv_distance = sqrt(inv_square_distance); + + inv_square_distance *= inv_distance; + inv_square_distance *= targetsPhysicalValues[idxTarget] * targetsPhysicalValues[idxSource]; + + dx *= inv_square_distance; + dy *= inv_square_distance; + dz *= inv_square_distance; + + targetsForcesX[idxTarget] += dx; + targetsForcesY[idxTarget] += dy; + targetsForcesZ[idxTarget] += dz; + targetsPotentials[idxTarget] += inv_distance * targetsPhysicalValues[idxSource]; + + targetsForcesX[idxSource] -= dx; + targetsForcesY[idxSource] -= dy; + targetsForcesZ[idxSource] -= dz; + targetsPotentials[idxSource] += inv_distance * targetsPhysicalValues[idxTarget]; + } + } + } + + /** + * + */ + template <class ContainerClass> + static void FullRemote(ContainerClass* const FRestrict inTargets, ContainerClass* const inNeighbors[], + const int limiteNeighbors){ + const int nbParticlesTargets = inTargets->getNbParticles(); + const FReal*const targetsPhysicalValues = inTargets->getPhysicalValues(); + const FReal*const targetsX = inTargets->getPositions()[0]; + const FReal*const targetsY = inTargets->getPositions()[1]; + const FReal*const targetsZ = inTargets->getPositions()[2]; + FReal*const targetsForcesX = inTargets->getForcesX(); + FReal*const targetsForcesY = inTargets->getForcesY(); + FReal*const targetsForcesZ = inTargets->getForcesZ(); + FReal*const targetsPotentials = inTargets->getPotentials(); + + for(int idxNeighbors = 0 ; idxNeighbors < limiteNeighbors ; ++idxNeighbors){ + for(int idxTarget = 0 ; idxTarget < nbParticlesTargets ; ++idxTarget){ + if( inNeighbors[idxNeighbors] ){ + const int nbParticlesSources = inNeighbors[idxNeighbors]->getNbParticles(); + const FReal*const sourcesPhysicalValues = inNeighbors[idxNeighbors]->getPhysicalValues(); + const FReal*const sourcesX = inNeighbors[idxNeighbors]->getPositions()[0]; + const FReal*const sourcesY = inNeighbors[idxNeighbors]->getPositions()[1]; + const FReal*const sourcesZ = inNeighbors[idxNeighbors]->getPositions()[2]; + + for(int idxSource = 0 ; idxSource < nbParticlesSources ; ++idxSource){ + double dx = sourcesX[idxSource] - targetsX[idxTarget]; + double dy = sourcesY[idxSource] - targetsY[idxTarget]; + double dz = sourcesZ[idxSource] - targetsZ[idxTarget]; + + double inv_square_distance = 1.0 / (dx*dx + dy*dy + dz*dz); + const double inv_distance = sqrt(inv_square_distance); + + inv_square_distance *= inv_distance; + inv_square_distance *= targetsPhysicalValues[idxTarget] * sourcesPhysicalValues[idxSource]; + + dx *= inv_square_distance; + dy *= inv_square_distance; + dz *= inv_square_distance; + + targetsForcesX[idxTarget] += dx; + targetsForcesY[idxTarget] += dy; + targetsForcesZ[idxTarget] += dz; + targetsPotentials[idxTarget] += inv_distance * sourcesPhysicalValues[idxSource]; + } + } + } + } + } + + /** P2P mutual interaction, + * this function computes the interaction for 2 particles. + * + * Formulas are: + * \f[ + * F = q_1 * q_2 / r^2 + * P_1 = q_2 / r ; P_2 = q_1 / r + * \f] + * In details : + * \f$ F(x) = \frac{ \Delta_x * q_1 * q_2 }{ r^2 } = \Delta_x * F \f$ + */ + static void MutualParticles(const FReal sourceX,const FReal sourceY,const FReal sourceZ, const FReal sourcePhysicalValue, + FReal* sourceForceX, FReal* sourceForceY, FReal* sourceForceZ, FReal* sourcePotential, + const FReal targetX,const FReal targetY,const FReal targetZ, const FReal targetPhysicalValue, + FReal* targetForceX, FReal* targetForceY, FReal* targetForceZ, FReal* targetPotential + ){ + FReal dx = sourceX - targetX; + FReal dy = sourceY - targetY; + FReal dz = sourceZ - targetZ; + + FReal inv_square_distance = FReal(1.0) / (dx*dx + dy*dy + dz*dz); + FReal inv_distance = FMath::Sqrt(inv_square_distance); + + inv_square_distance *= inv_distance; + inv_square_distance *= targetPhysicalValue * sourcePhysicalValue; + + dx *= inv_square_distance; + dy *= inv_square_distance; + dz *= inv_square_distance; + + *targetForceX += dx; + *targetForceY += dy; + *targetForceZ += dz; + *targetPotential += ( inv_distance * sourcePhysicalValue ); + + *sourceForceX -= dx; + *sourceForceY -= dy; + *sourceForceZ -= dz; + *sourcePotential += ( inv_distance * targetPhysicalValue ); + } + + /** P2P mutual interaction, + * this function computes the interaction for 2 particles. + * + * Formulas are: + * \f[ + * F = q_1 * q_2 / r^2 + * P_1 = q_2 / r ; P_2 = q_1 / r + * \f] + * In details : + * \f$ F(x) = \frac{ \Delta_x * q_1 * q_2 }{ r^2 } = \Delta_x * F \f$ + */ + static void NonMutualParticles(const FReal sourceX,const FReal sourceY,const FReal sourceZ, const FReal sourcePhysicalValue, + const FReal targetX,const FReal targetY,const FReal targetZ, const FReal targetPhysicalValue, + FReal* targetForceX, FReal* targetForceY, FReal* targetForceZ, FReal* targetPotential){ + FReal dx = sourceX - targetX; + FReal dy = sourceY - targetY; + FReal dz = sourceZ - targetZ; + + FReal inv_square_distance = FReal(1.0) / (dx*dx + dy*dy + dz*dz); + FReal inv_distance = FMath::Sqrt(inv_square_distance); + + inv_square_distance *= inv_distance; + inv_square_distance *= targetPhysicalValue * sourcePhysicalValue; + + dx *= inv_square_distance; + dy *= inv_square_distance; + dz *= inv_square_distance; + + *targetForceX += dx; + *targetForceY += dy; + *targetForceZ += dz; + *targetPotential += ( inv_distance * sourcePhysicalValue ); + } + + template <class ContainerClass> + static void FullMutualLJ(ContainerClass* const FRestrict inTargets, ContainerClass* const inNeighbors[], + const int limiteNeighbors){ + + const int nbParticlesTargets = inTargets->getNbParticles(); + const FReal*const targetsPhysicalValues = inTargets->getPhysicalValues(); + const FReal*const targetsX = inTargets->getPositions()[0]; + const FReal*const targetsY = inTargets->getPositions()[1]; + const FReal*const targetsZ = inTargets->getPositions()[2]; + FReal*const targetsForcesX = inTargets->getForcesX(); + FReal*const targetsForcesY = inTargets->getForcesY(); + FReal*const targetsForcesZ = inTargets->getForcesZ(); + FReal*const targetsPotentials = inTargets->getPotentials(); + + for(int idxNeighbors = 0 ; idxNeighbors < limiteNeighbors ; ++idxNeighbors){ + for(int idxTarget = 0 ; idxTarget < nbParticlesTargets ; ++idxTarget){ + if( inNeighbors[idxNeighbors] ){ + const int nbParticlesSources = inNeighbors[idxNeighbors]->getNbParticles(); + const FReal*const sourcesPhysicalValues = inNeighbors[idxNeighbors]->getPhysicalValues(); + const FReal*const sourcesX = inNeighbors[idxNeighbors]->getPositions()[0]; + const FReal*const sourcesY = inNeighbors[idxNeighbors]->getPositions()[1]; + const FReal*const sourcesZ = inNeighbors[idxNeighbors]->getPositions()[2]; + FReal*const sourcesForcesX = inNeighbors[idxNeighbors]->getForcesX(); + FReal*const sourcesForcesY = inNeighbors[idxNeighbors]->getForcesY(); + FReal*const sourcesForcesZ = inNeighbors[idxNeighbors]->getForcesZ(); + FReal*const sourcesPotentials = inNeighbors[idxNeighbors]->getPotentials(); + + for(int idxSource = 0 ; idxSource < nbParticlesSources ; ++idxSource){ + FReal dx = sourcesX[idxSource] - targetsX[idxTarget]; + FReal dy = sourcesY[idxSource] - targetsY[idxTarget]; + FReal dz = sourcesZ[idxSource] - targetsZ[idxTarget]; + + FReal inv_distance_pow2 = FReal(1.0) / (dx*dx + dy*dy + dz*dz); + FReal inv_distance = FMath::Sqrt(inv_distance_pow2); + FReal inv_distance_pow3 = inv_distance_pow2 * inv_distance; + FReal inv_distance_pow6 = inv_distance_pow3 * inv_distance_pow3; + FReal inv_distance_pow8 = inv_distance_pow6 * inv_distance_pow2; + + FReal coef = ((targetsPhysicalValues[idxTarget] * sourcesPhysicalValues[idxSource]) + * (FReal(12.0)*inv_distance_pow6*inv_distance_pow8 - FReal(6.0)*inv_distance_pow8)); + FReal potentialCoef = (inv_distance_pow6*inv_distance_pow6-inv_distance_pow6); + + dx *= coef; + dy *= coef; + dz *= coef; + + targetsForcesX[idxTarget] += dx; + targetsForcesY[idxTarget] += dy; + targetsForcesZ[idxTarget] += dz; + targetsPotentials[idxTarget] += ( potentialCoef * sourcesPhysicalValues[idxSource] ); + + sourcesForcesX[idxSource] -= dx; + sourcesForcesY[idxSource] -= dy; + sourcesForcesZ[idxSource] -= dz; + sourcesPotentials[idxSource] += potentialCoef * targetsPhysicalValues[idxTarget]; + } + } + } + } + + for(int idxTarget = 0 ; idxTarget < nbParticlesTargets ; ++idxTarget){ + for(int idxSource = idxTarget + 1 ; idxSource < nbParticlesTargets ; ++idxSource){ + FReal dx = targetsX[idxSource] - targetsX[idxTarget]; + FReal dy = targetsY[idxSource] - targetsY[idxTarget]; + FReal dz = targetsZ[idxSource] - targetsZ[idxTarget]; + + FReal inv_distance_pow2 = FReal(1.0) / (dx*dx + dy*dy + dz*dz); + FReal inv_distance = FMath::Sqrt(inv_distance_pow2); + FReal inv_distance_pow3 = inv_distance_pow2 * inv_distance; + FReal inv_distance_pow6 = inv_distance_pow3 * inv_distance_pow3; + FReal inv_distance_pow8 = inv_distance_pow6 * inv_distance_pow2; + + FReal coef = ((targetsPhysicalValues[idxTarget] * targetsPhysicalValues[idxSource]) + * (FReal(12.0)*inv_distance_pow6*inv_distance_pow8 - FReal(6.0)*inv_distance_pow8)); + FReal potentialCoef = (inv_distance_pow6*inv_distance_pow6-inv_distance_pow6); + + dx *= coef; + dy *= coef; + dz *= coef; + + targetsForcesX[idxTarget] += dx; + targetsForcesY[idxTarget] += dy; + targetsForcesZ[idxTarget] += dz; + targetsPotentials[idxTarget] += ( potentialCoef * targetsPhysicalValues[idxSource] ); + + targetsForcesX[idxSource] -= dx; + targetsForcesY[idxSource] -= dy; + targetsForcesZ[idxSource] -= dz; + targetsPotentials[idxSource] += potentialCoef * targetsPhysicalValues[idxTarget]; + } + } + } + + /** + * + */ + template <class ContainerClass> + static void FullRemoteLJ(ContainerClass* const FRestrict inTargets, ContainerClass* const inNeighbors[], + const int limiteNeighbors){ + const int nbParticlesTargets = inTargets->getNbParticles(); + const FReal*const targetsPhysicalValues = inTargets->getPhysicalValues(); + const FReal*const targetsX = inTargets->getPositions()[0]; + const FReal*const targetsY = inTargets->getPositions()[1]; + const FReal*const targetsZ = inTargets->getPositions()[2]; + FReal*const targetsForcesX = inTargets->getForcesX(); + FReal*const targetsForcesY = inTargets->getForcesY(); + FReal*const targetsForcesZ = inTargets->getForcesZ(); + FReal*const targetsPotentials = inTargets->getPotentials(); + + for(int idxNeighbors = 0 ; idxNeighbors < limiteNeighbors ; ++idxNeighbors){ + for(int idxTarget = 0 ; idxTarget < nbParticlesTargets ; ++idxTarget){ + if( inNeighbors[idxNeighbors] ){ + const int nbParticlesSources = inNeighbors[idxNeighbors]->getNbParticles(); + const FReal*const sourcesPhysicalValues = inNeighbors[idxNeighbors]->getPhysicalValues(); + const FReal*const sourcesX = inNeighbors[idxNeighbors]->getPositions()[0]; + const FReal*const sourcesY = inNeighbors[idxNeighbors]->getPositions()[1]; + const FReal*const sourcesZ = inNeighbors[idxNeighbors]->getPositions()[2]; + + for(int idxSource = 0 ; idxSource < nbParticlesSources ; ++idxSource){ + // lenard-jones potential + FReal dx = sourcesX[idxSource] - targetsX[idxTarget]; + FReal dy = sourcesY[idxSource] - targetsY[idxTarget]; + FReal dz = sourcesZ[idxSource] - targetsZ[idxTarget]; + + FReal inv_distance_pow2 = FReal(1.0) / (dx*dx + dy*dy + dz*dz); + FReal inv_distance = FMath::Sqrt(inv_distance_pow2); + FReal inv_distance_pow3 = inv_distance_pow2 * inv_distance; + FReal inv_distance_pow6 = inv_distance_pow3 * inv_distance_pow3; + FReal inv_distance_pow8 = inv_distance_pow6 * inv_distance_pow2; + + FReal coef = ((targetsPhysicalValues[idxTarget] * sourcesPhysicalValues[idxSource]) + * (FReal(12.0)*inv_distance_pow6*inv_distance_pow8 - FReal(6.0)*inv_distance_pow8)); + + dx *= coef; + dy *= coef; + dz *= coef; + + targetsForcesX[idxTarget] += dx; + targetsForcesY[idxTarget] += dy; + targetsForcesZ[idxTarget] += dz; + targetsPotentials[idxTarget] += ( (inv_distance_pow6*inv_distance_pow6-inv_distance_pow6) * sourcesPhysicalValues[idxSource] ); + } + } + } + } + } + + + /** + * @brief NonMutualParticlesLJ + * @param sourceX + * @param sourceY + * @param sourceZ + * @param sourcePhysicalValue + * @param targetX + * @param targetY + * @param targetZ + * @param targetPhysicalValue + * @param targetForceX + * @param targetForceY + * @param targetForceZ + * @param targetPotential + */ + static void NonMutualParticlesLJ(const FReal sourceX,const FReal sourceY,const FReal sourceZ, const FReal sourcePhysicalValue, + const FReal targetX,const FReal targetY,const FReal targetZ, const FReal targetPhysicalValue, + FReal* targetForceX, FReal* targetForceY, FReal* targetForceZ, FReal* targetPotential){ + // lenard-jones potential + FReal dx = sourceX - targetX; + FReal dy = sourceY - targetY; + FReal dz = sourceZ - targetZ; + + FReal inv_distance_pow2 = FReal(1.0) / (dx*dx + dy*dy + dz*dz); + FReal inv_distance = FMath::Sqrt(inv_distance_pow2); + FReal inv_distance_pow3 = inv_distance_pow2 * inv_distance; + FReal inv_distance_pow6 = inv_distance_pow3 * inv_distance_pow3; + FReal inv_distance_pow8 = inv_distance_pow6 * inv_distance_pow2; + + FReal coef = ((targetPhysicalValue * sourcePhysicalValue) * (FReal(12.0)*inv_distance_pow6*inv_distance_pow8 + - FReal(6.0)*inv_distance_pow8)); + + dx *= coef; + dy *= coef; + dz *= coef; + + (*targetForceX) += dx; + (*targetForceY) += dy; + (*targetForceZ) += dz; + (*targetPotential) += ( (inv_distance_pow6*inv_distance_pow6-inv_distance_pow6) * sourcePhysicalValue ); + } + + /** + * @brief MutualParticlesLJ + * @param sourceX + * @param sourceY + * @param sourceZ + * @param sourcePhysicalValue + * @param sourceForceX + * @param sourceForceY + * @param sourceForceZ + * @param sourcePotential + * @param targetX + * @param targetY + * @param targetZ + * @param targetPhysicalValue + * @param targetForceX + * @param targetForceY + * @param targetForceZ + * @param targetPotential + */ + static void MutualParticlesLJ(const FReal sourceX,const FReal sourceY,const FReal sourceZ, const FReal sourcePhysicalValue, + FReal* sourceForceX, FReal* sourceForceY, FReal* sourceForceZ, FReal* sourcePotential, + const FReal targetX,const FReal targetY,const FReal targetZ, const FReal targetPhysicalValue, + FReal* targetForceX, FReal* targetForceY, FReal* targetForceZ, FReal* targetPotential + ){ + // lenard-jones potential + FReal dx = sourceX - targetX; + FReal dy = sourceY - targetY; + FReal dz = sourceZ - targetZ; + + FReal inv_distance_pow2 = FReal(1.0) / (dx*dx + dy*dy + dz*dz); + FReal inv_distance = FMath::Sqrt(inv_distance_pow2); + FReal inv_distance_pow3 = inv_distance_pow2 * inv_distance; + FReal inv_distance_pow6 = inv_distance_pow3 * inv_distance_pow3; + FReal inv_distance_pow8 = inv_distance_pow6 * inv_distance_pow2; + + FReal coef = ((targetPhysicalValue * sourcePhysicalValue) * (FReal(12.0)*inv_distance_pow6*inv_distance_pow8 + - FReal(6.0)*inv_distance_pow8)); + FReal potentialCoef = (inv_distance_pow6*inv_distance_pow6-inv_distance_pow6); + + dx *= coef; + dy *= coef; + dz *= coef; + + (*targetForceX) += dx; + (*targetForceY) += dy; + (*targetForceZ) += dz; + (*targetPotential) += ( potentialCoef * sourcePhysicalValue ); + + (*sourceForceX) -= dx; + (*sourceForceY) -= dy; + (*sourceForceZ) -= dz; + (*sourcePotential) += ( potentialCoef * targetPhysicalValue ); + } +}; + +#endif // FP2P_HPP diff --git a/Src/Kernels/P2P/FP2PParticleContainer.hpp b/Src/Kernels/P2P/FP2PParticleContainer.hpp new file mode 100644 index 000000000..0c881bbaa --- /dev/null +++ b/Src/Kernels/P2P/FP2PParticleContainer.hpp @@ -0,0 +1,66 @@ +// =================================================================================== +// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner +// olivier.coulaud@inria.fr, berenger.bramas@inria.fr +// This software is a computer program whose purpose is to compute the FMM. +// +// This software is governed by the CeCILL-C and LGPL licenses and +// abiding by the rules of distribution of free software. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public and CeCILL-C Licenses for more details. +// "http://www.cecill.info". +// "http://www.gnu.org/licenses". +// =================================================================================== +#ifndef FP2PPARTICLECONTAINER_HPP +#define FP2PPARTICLECONTAINER_HPP + +#include "../../Components/FBasicParticleContainer.hpp" + +class FP2PParticleContainer : public FBasicParticleContainer<5> { + typedef FBasicParticleContainer<5> Parent; + +public: + FReal* getPhysicalValues(){ + return Parent::getAttribute<0>(); + } + + const FReal* getPhysicalValues() const { + return Parent::getAttribute<0>(); + } + + FReal* getPotentials(){ + return Parent::getAttribute<1>(); + } + + const FReal* getPotentials() const { + return Parent::getAttribute<1>(); + } + + FReal* getForcesX(){ + return Parent::getAttribute<2>(); + } + + const FReal* getForcesX() const { + return Parent::getAttribute<2>(); + } + + FReal* getForcesY(){ + return Parent::getAttribute<3>(); + } + + const FReal* getForcesY() const { + return Parent::getAttribute<3>(); + } + + FReal* getForcesZ(){ + return Parent::getAttribute<4>(); + } + + const FReal* getForcesZ() const { + return Parent::getAttribute<4>(); + } +}; + +#endif // FP2PPARTICLECONTAINER_HPP diff --git a/Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp b/Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp new file mode 100644 index 000000000..e379d6589 --- /dev/null +++ b/Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp @@ -0,0 +1,25 @@ +#ifndef FP2PPARTICLECONTAINERINDEXED_HPP +#define FP2PPARTICLECONTAINERINDEXED_HPP + +#include "../../Containers/FVector.hpp" + +#include "FP2PParticleContainer.hpp" + +class FP2PParticleContainerIndexed : public FP2PParticleContainer { + typedef FP2PParticleContainer Parent; + + FVector<int> indexes; + +public: + template<typename... Args> + void push(const FPoint& inParticlePosition, const int index, Args... args){ + Parent::push(inParticlePosition, args... ); + indexes.push(index); + } + + const FVector<int>& getIndexes() const{ + return indexes; + } +}; + +#endif // FP2PPARTICLECONTAINERINDEXED_HPP diff --git a/Src/Kernels/Rotation/FRotationKernel.hpp b/Src/Kernels/Rotation/FRotationKernel.hpp index a59b4894f..1e0404491 100755 --- a/Src/Kernels/Rotation/FRotationKernel.hpp +++ b/Src/Kernels/Rotation/FRotationKernel.hpp @@ -22,6 +22,7 @@ #include "../../Utils/FMemUtils.hpp" #include "../../Utils/FSpherical.hpp" +#include "../P2P/FP2P.hpp" /** This is a recursion to get the minimal size of the matrix dlmk */ @@ -43,8 +44,8 @@ template<> struct NumberOfValuesInDlmk<0>{ * Here is the optimizated kernel, please refer to FRotationOriginalKernel * to see the non optimized easy to understand kernel. */ -template< class ParticleClass, class CellClass, class ContainerClass, int P> -class FRotationKernel : public FAbstractKernels<ParticleClass,CellClass,ContainerClass> { +template< class CellClass, class ContainerClass, int P> +class FRotationKernel : public FAbstractKernels<CellClass,ContainerClass> { //< Size of the data array computed using a suite relation static const int SizeArray = ((P+2)*(P+1))/2; @@ -918,14 +919,18 @@ public: FReal angles[P+1][2]; // For all particles in the leaf box - typename ContainerClass::ConstBasicIterator iterParticle(*inParticles); - while( iterParticle.hasNotFinished()){ + const FReal*const physicalValues = inParticles->getPhysicalValues(); + const FReal*const positionsX = inParticles->getPositions()[0]; + const FReal*const positionsY = inParticles->getPositions()[1]; + const FReal*const positionsZ = inParticles->getPositions()[2]; + + for(int idxPart = 0 ; idxPart < inParticles->getNbParticles() ; ++ idxPart){ // P2M - const ParticleClass& particle = iterParticle.data(); - const FSpherical sph(particle.getPosition() - cellPosition); + const FPoint position(positionsX[idxPart],positionsY[idxPart],positionsZ[idxPart]); + const FSpherical sph(position - cellPosition); // The physical value (charge, mass) - const FReal q = particle.getPhysicalValue(); + const FReal q = physicalValues[idxPart]; // The distance between the SH and the particle const FReal a = sph.getR(); @@ -950,9 +955,6 @@ public: } q_aPowL *= a; } - - // Goto next particle - iterParticle.gotoNext(); } } @@ -1152,11 +1154,19 @@ public: const FPoint cellPosition = getLeafCenter(inLocal->getCoordinate()); // For all particles in the leaf box - typename ContainerClass::BasicIterator iterParticle(*inParticles); - while( iterParticle.hasNotFinished()){ + const FReal*const physicalValues = inParticles->getPhysicalValues(); + const FReal*const positionsX = inParticles->getPositions()[0]; + const FReal*const positionsY = inParticles->getPositions()[1]; + const FReal*const positionsZ = inParticles->getPositions()[2]; + FReal*const forcesX = inParticles->getForcesX(); + FReal*const forcesY = inParticles->getForcesY(); + FReal*const forcesZ = inParticles->getForcesZ(); + FReal*const potentials = inParticles->getPotentials(); + + for(int idxPart = 0 ; idxPart < inParticles->getNbParticles() ; ++ idxPart){ // L2P - ParticleClass& particle = iterParticle.data(); - const FSpherical sph(particle.getPosition() - cellPosition); + const FPoint position(positionsX[idxPart],positionsY[idxPart],positionsZ[idxPart]); + const FSpherical sph(position - cellPosition); // The distance between the SH and the particle const FReal r = sph.getR(); @@ -1242,7 +1252,7 @@ public: // copy variable from spherical position const FReal cosPhi = FMath::Cos(sph.getPhi()); const FReal sinPhi = FMath::Sin(sph.getPhi()); - const FReal physicalValue = particle.getPhysicalValue(); + const FReal physicalValue = physicalValues[idxPart]; // compute forces const FReal forceX = ( @@ -1260,7 +1270,9 @@ public: (-sph.getSinTheta()) * FO) * physicalValue; // inc particles forces - particle.incForces( forceX, forceY, forceZ ); + forcesX[idxPart] += forceX; + forcesY[idxPart] += forceY; + forcesZ[idxPart] += forceZ; } // compute the potential { @@ -1281,10 +1293,8 @@ public: } } // inc potential - particle.incPotential(magnitude); + potentials[idxPart] += magnitude; } - // progress - iterParticle.gotoNext(); } } @@ -1298,44 +1308,7 @@ public: void P2P(const FTreeCoordinate& /*inPosition*/, ContainerClass* const FRestrict inTargets, const ContainerClass* const FRestrict /*inSources*/, ContainerClass* const inNeighbors[27], const int /*inSize*/){ - - { - typename ContainerClass::BasicIterator iterTarget(*inTargets); - while( iterTarget.hasNotFinished() ){ - // We copy the target particle to work with a particle in the heap - ParticleClass target( iterTarget.data() ); - - // For all particles after the current one - typename ContainerClass::BasicIterator iterSameBox = iterTarget; - iterSameBox.gotoNext(); - while( iterSameBox.hasNotFinished() ){ - particlesMutualInteraction(&target, &iterSameBox.data()); - iterSameBox.gotoNext(); - } - // Set data and progress - iterTarget.setData(target); - iterTarget.gotoNext(); - } - } - // For all the neigbors leaves - for(int idxDirectNeighbors = 0 ; idxDirectNeighbors <= 13 ; ++idxDirectNeighbors){ - if( inNeighbors[idxDirectNeighbors] ){ - // For all particles in current leaf - typename ContainerClass::BasicIterator iterTarget(*inTargets); - while( iterTarget.hasNotFinished() ){ - ParticleClass target( iterTarget.data() ); - // For all the particles in the other leaf - typename ContainerClass::BasicIterator iterSource(*inNeighbors[idxDirectNeighbors]); - while( iterSource.hasNotFinished() ){ - particlesMutualInteraction(&target, &iterSource.data()); - iterSource.gotoNext(); - } - // Set data and progress - iterTarget.setData(target); - iterTarget.gotoNext(); - } - } - } + FP2P::FullMutual(inTargets,inNeighbors,14); } @@ -1343,91 +1316,7 @@ public: void P2PRemote(const FTreeCoordinate& /*inPosition*/, ContainerClass* const FRestrict inTargets, const ContainerClass* const FRestrict /*inSources*/, ContainerClass* const inNeighbors[27], const int /*inSize*/){ - for(int idxDirectNeighbors = 0 ; idxDirectNeighbors < 27 ; ++idxDirectNeighbors){ - if( inNeighbors[idxDirectNeighbors] ){ - // For all particles in current leaf - typename ContainerClass::BasicIterator iterTarget(*inTargets); - while( iterTarget.hasNotFinished() ){ - ParticleClass target( iterTarget.data() ); - // For all the particles in the other leaf - typename ContainerClass::BasicIterator iterSource(*inNeighbors[idxDirectNeighbors]); - while( iterSource.hasNotFinished() ){ - particlesInteraction(&target, iterSource.data()); - iterSource.gotoNext(); - } - // Set data and progress - iterTarget.setData(target); - iterTarget.gotoNext(); - } - } - } - } - -public: - /** P2P mutual interaction, - * this function computes the interaction for 2 particles. - * - * Formulas are: - * \f[ - * F = q_1 * q_2 / r^2 - * P_1 = q_2 / r ; P_2 = q_1 / r - * \f] - * In details : - * \f$ F(x) = \frac{ \Delta_x * q_1 * q_2 }{ r^2 } = \Delta_x * F \f$ - */ - void particlesMutualInteraction(ParticleClass*const FRestrict target, ParticleClass*const FRestrict source) const { - - FReal dx = source->getPosition().getX() - target->getPosition().getX(); - FReal dy = source->getPosition().getY() - target->getPosition().getY(); - FReal dz = source->getPosition().getZ() - target->getPosition().getZ(); - - FReal inv_square_distance = FReal(1.0) / (dx*dx + dy*dy + dz*dz); - FReal inv_distance = FMath::Sqrt(inv_square_distance); - - inv_square_distance *= inv_distance; - inv_square_distance *= target->getPhysicalValue() * source->getPhysicalValue(); - - dx *= inv_square_distance; - dy *= inv_square_distance; - dz *= inv_square_distance; - - target->incForces( dx, dy, dz); - target->incPotential( inv_distance * source->getPhysicalValue() ); - - source->incForces( (-dx), (-dy), (-dz)); - source->incPotential( inv_distance * target->getPhysicalValue() ); - - } - - /** P2P mutual interaction, - * this function computes the interaction for 2 particles. - * - * Formulas are: - * \f[ - * F = q_1 * q_2 / r^2 - * P_1 = q_2 / r ; P_2 = q_1 / r - * \f] - * In details : - * \f$ F(x) = \frac{ \Delta_x * q_1 * q_2 }{ r^2 } = \Delta_x * F \f$ - */ - void particlesInteraction(ParticleClass*const FRestrict target, const ParticleClass& source) const { - - FReal dx = source.getPosition().getX() - target->getPosition().getX(); - FReal dy = source.getPosition().getY() - target->getPosition().getY(); - FReal dz = source.getPosition().getZ() - target->getPosition().getZ(); - - FReal inv_square_distance = FReal(1.0) / (dx*dx + dy*dy + dz*dz); - FReal inv_distance = FMath::Sqrt(inv_square_distance); - - inv_square_distance *= inv_distance; - inv_square_distance *= target->getPhysicalValue() * source.getPhysicalValue(); - - dx *= inv_square_distance; - dy *= inv_square_distance; - dz *= inv_square_distance; - - target->incForces( dx, dy, dz); - target->incPotential( inv_distance * source.getPhysicalValue() ); + FP2P::FullRemote(inTargets,inNeighbors,27); } }; diff --git a/Src/Kernels/Rotation/FRotationOriginalKernel.hpp b/Src/Kernels/Rotation/FRotationOriginalKernel.hpp index c7ec5f06a..d1b77cc43 100755 --- a/Src/Kernels/Rotation/FRotationOriginalKernel.hpp +++ b/Src/Kernels/Rotation/FRotationOriginalKernel.hpp @@ -22,6 +22,7 @@ #include "../../Utils/FMemUtils.hpp" #include "../../Utils/FSpherical.hpp" +#include "../P2P/FP2P.hpp" /** * @author Berenger Bramas (berenger.bramas@inria.fr) @@ -47,8 +48,8 @@ * } * @endcode */ -template< class ParticleClass, class CellClass, class ContainerClass, int P> -class FRotationOriginalKernel : public FAbstractKernels<ParticleClass,CellClass,ContainerClass> { +template< class CellClass, class ContainerClass, int P> +class FRotationOriginalKernel : public FAbstractKernels<CellClass,ContainerClass> { //< Size of the data array computed using a suite relation static const int SizeArray = ((P+2)*(P+1))/2; @@ -454,14 +455,18 @@ public: FReal legendre[SizeArray]; // For all particles in the leaf box - typename ContainerClass::ConstBasicIterator iterParticle(*inParticles); - while( iterParticle.hasNotFinished()){ + const FReal*const physicalValues = inParticles.getPhysicalValues(); + const FReal*const positionsX = inParticles.getPositions()[0]; + const FReal*const positionsY = inParticles.getPositions()[1]; + const FReal*const positionsZ = inParticles.getPositions()[2]; + + for(int idxPart = 0 ; idxPart < inParticles.getNbParticles() ; ++ idxPart){ // P2M - const ParticleClass& particle = iterParticle.data(); - const FSpherical sph(particle.getPosition() - cellPosition); + const FPoint position(positionsX[idxPart],positionsY[idxPart],positionsZ[idxPart]); + const FSpherical sph(position - cellPosition); // The physical value (charge, mass) - const FReal q = particle.getPhysicalValue(); + const FReal q = physicalValues[idxPart]; // The distance between the SH and the particle const FReal a = sph.getR(); @@ -477,9 +482,6 @@ public: w[atLm(l,m)].incImag(magnitude * FMath::Sin(FReal(m) * sph.getPhi() + i_pow_m[m & 0x3])); } } - - // Goto next particle - iterParticle.gotoNext(); } } @@ -664,11 +666,19 @@ public: const FPoint cellPosition = getLeafCenter(inLocal->getCoordinate()); // For all particles in the leaf box - typename ContainerClass::BasicIterator iterParticle(*inParticles); - while( iterParticle.hasNotFinished()){ + const FReal*const physicalValues = inParticles.getPhysicalValues(); + const FReal*const positionsX = inParticles.getPositions()[0]; + const FReal*const positionsY = inParticles.getPositions()[1]; + const FReal*const positionsZ = inParticles.getPositions()[2]; + const FReal*const forcesX = inParticles.getForcesX(); + const FReal*const forcesY = inParticles.getForcesY(); + const FReal*const forcesZ = inParticles.getForcesZ(); + const FReal*const potentials = inParticles.getPotentials(); + + for(int idxPart = 0 ; idxPart < inParticles.getNbParticles() ; ++ idxPart){ // L2P - ParticleClass& particle = iterParticle.data(); - const FSpherical sph(particle.getPosition() - cellPosition); + const FPoint position(positionsX[idxPart],positionsY[idxPart],positionsZ[idxPart]); + const FSpherical sph(position - cellPosition); // The distance between the SH and the particle const FReal r = sph.getR(); @@ -727,7 +737,7 @@ public: // copy variable from spherical position const FReal cosPhi = FMath::Cos(sph.getPhi()); const FReal sinPhi = FMath::Sin(sph.getPhi()); - const FReal physicalValue = particle.getPhysicalValue(); + const FReal physicalValue = physicalValues[idxPart]; // compute forces const FReal forceX = ( @@ -745,7 +755,9 @@ public: (-sph.getSinTheta()) * FO) * physicalValue; // inc particles forces - particle.incForces( forceX, forceY, forceZ ); + forcesX[idxPart] += forceX; + forcesY[idxPart] += forceY; + forcesZ[idxPart] += forceZ; } { // Result for potential @@ -767,14 +779,18 @@ public: } } // inc potential - particle.incPotential(magnitude); + potentials[idxPart] += magnitude; } - // progress - iterParticle.gotoNext(); } } + /** P2P + * This function proceed the P2P using particlesMutualInteraction + * The computation is done for interactions with an index <= 13. + * (13 means current leaf (x;y;z) = (0;0;0)). + * Calling this method in multi thread should be done carrefully. + */ /** P2P * This function proceed the P2P using particlesMutualInteraction * The computation is done for interactions with an index <= 13. @@ -784,104 +800,15 @@ public: void P2P(const FTreeCoordinate& /*inPosition*/, ContainerClass* const FRestrict inTargets, const ContainerClass* const FRestrict /*inSources*/, ContainerClass* const inNeighbors[27], const int /*inSize*/){ - - { - typename ContainerClass::BasicIterator iterTarget(*inTargets); - while( iterTarget.hasNotFinished() ){ - // We copy the target particle to work with a particle in the heap - ParticleClass target( iterTarget.data() ); - - // For all particles after the current one - typename ContainerClass::BasicIterator iterSameBox = iterTarget; - iterSameBox.gotoNext(); - while( iterSameBox.hasNotFinished() ){ - particlesMutualInteraction(&target, &iterSameBox.data()); - iterSameBox.gotoNext(); - } - // Set data and progress - iterTarget.setData(target); - iterTarget.gotoNext(); - } - } - // For all the neigbors leaves - for(int idxDirectNeighbors = 0 ; idxDirectNeighbors <= 13 ; ++idxDirectNeighbors){ - if( inNeighbors[idxDirectNeighbors] ){ - // For all particles in current leaf - typename ContainerClass::BasicIterator iterTarget(*inTargets); - while( iterTarget.hasNotFinished() ){ - ParticleClass target( iterTarget.data() ); - // For all the particles in the other leaf - typename ContainerClass::BasicIterator iterSource(*inNeighbors[idxDirectNeighbors]); - while( iterSource.hasNotFinished() ){ - particlesMutualInteraction(&target, &iterSource.data()); - iterSource.gotoNext(); - } - // Set data and progress - iterTarget.setData(target); - iterTarget.gotoNext(); - } - } - } + FP2P::FullMutual(inTargets,inNeighbors,14); } /** Use mutual even if it not useful and call particlesMutualInteraction */ - void P2PRemote(const FTreeCoordinate& inPosition, - ContainerClass* const FRestrict inTargets, const ContainerClass* const FRestrict inSources, - ContainerClass* const inNeighbors[27], const int inSize){ - for(int idxDirectNeighbors = 0 ; idxDirectNeighbors < 27 ; ++idxDirectNeighbors){ - if( inNeighbors[idxDirectNeighbors] ){ - // For all particles in current leaf - typename ContainerClass::BasicIterator iterTarget(*inTargets); - while( iterTarget.hasNotFinished() ){ - ParticleClass target( iterTarget.data() ); - // For all the particles in the other leaf - typename ContainerClass::BasicIterator iterSource(*inNeighbors[idxDirectNeighbors]); - while( iterSource.hasNotFinished() ){ - particlesMutualInteraction(&target, &iterSource.data()); - iterSource.gotoNext(); - } - // Set data and progress - iterTarget.setData(target); - iterTarget.gotoNext(); - } - } - } - } - - /** P2P mutual interaction, - * this function computes the interaction for 2 particles. - * - * Formulas are: - * \f[ - * F = q_1 * q_2 / r^2 - * P_1 = q_2 / r ; P_2 = q_1 / r - * \f] - * In details : - * \f$ F(x) = \frac{ \Delta_x * q_1 * q_2 }{ r^2 } = \Delta_x * F \f$ - */ - void particlesMutualInteraction(ParticleClass*const FRestrict target, ParticleClass*const FRestrict source) const { - - FReal dx = source->getPosition().getX() - target->getPosition().getX(); - FReal dy = source->getPosition().getY() - target->getPosition().getY(); - FReal dz = source->getPosition().getZ() - target->getPosition().getZ(); - - FReal inv_square_distance = FReal(1.0) / (dx*dx + dy*dy + dz*dz); - FReal inv_distance = FMath::Sqrt(inv_square_distance); - - inv_square_distance *= inv_distance; - inv_square_distance *= target->getPhysicalValue() * source->getPhysicalValue(); - - dx *= inv_square_distance; - dy *= inv_square_distance; - dz *= inv_square_distance; - - target->incForces( dx, dy, dz); - target->incPotential( inv_distance * source->getPhysicalValue() ); - - source->incForces( (-dx), (-dy), (-dz)); - source->incPotential( inv_distance * target->getPhysicalValue() ); - + void P2PRemote(const FTreeCoordinate& /*inPosition*/, + ContainerClass* const FRestrict inTargets, const ContainerClass* const FRestrict /*inSources*/, + ContainerClass* const inNeighbors[27], const int /*inSize*/){ + FP2P::FullRemote(inTargets,inNeighbors,27); } }; diff --git a/Src/Kernels/Rotation/FRotationParticle.hpp b/Src/Kernels/Rotation/FRotationParticle.hpp deleted file mode 100755 index 0e857d023..000000000 --- a/Src/Kernels/Rotation/FRotationParticle.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== -#ifndef FROTATIONLPARTICLE_HPP -#define FROTATIONLPARTICLE_HPP - -#include "../../Extensions/FExtendForces.hpp" -#include "../../Extensions/FExtendPotential.hpp" -#include "../../Extensions/FExtendParticleType.hpp" -#include "../../Components/FFmaParticle.hpp" - -#include "../../Components/FAbstractSerializable.hpp" - -class FRotationParticle : public FExtendForces, public FFmaParticle, public FExtendPotential { -public: - - /** Save current object */ - void save(FBufferWriter& buffer) const { - FExtendForces::save(buffer); - FFmaParticle::save(buffer); - FExtendPotential::save(buffer); - } - /** Retrieve current object */ - void restore(FBufferReader& buffer) { - FExtendForces::restore(buffer); - FFmaParticle::restore(buffer); - FExtendPotential::restore(buffer); - } -}; - - -class FTypedRotationParticle : public FRotationParticle, public FExtendParticleType { -public: - /** Save current object */ - void save(FBufferWriter& buffer) const { - FRotationParticle::save(buffer); - FExtendParticleType::save(buffer); - } - /** Retrieve current object */ - void restore(FBufferReader& buffer) { - FRotationParticle::restore(buffer); - FExtendParticleType::restore(buffer); - } -}; - -#endif // FROTATIONLPARTICLE_HPP diff --git a/Src/Kernels/Rotation/FRotationParticleContainer.hpp b/Src/Kernels/Rotation/FRotationParticleContainer.hpp new file mode 100755 index 000000000..82f5fc073 --- /dev/null +++ b/Src/Kernels/Rotation/FRotationParticleContainer.hpp @@ -0,0 +1,66 @@ +// =================================================================================== +// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner +// olivier.coulaud@inria.fr, berenger.bramas@inria.fr +// This software is a computer program whose purpose is to compute the FMM. +// +// This software is governed by the CeCILL-C and LGPL licenses and +// abiding by the rules of distribution of free software. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public and CeCILL-C Licenses for more details. +// "http://www.cecill.info". +// "http://www.gnu.org/licenses". +// =================================================================================== +#ifndef FROTATIONLPARTICLECONTAINER_HPP +#define FROTATIONLPARTICLECONTAINER_HPP + + +#include "../../Components/FBasicParticleContainer.hpp" + +class FRotationParticleContainer : public FBasicParticleContainer<5> { + typedef FBasicParticleContainer<5> Parent; +public: + FReal* getPhysicalValues(){ + return Parent::getAttribute(0); + } + + const FReal* getPhysicalValues() const { + return Parent::getAttribute(0); + } + + FReal* getPotentials(){ + return Parent::getAttribute(1); + } + + const FReal* getPotentials() const { + return Parent::getAttribute(1); + } + + FReal* getForcesX(){ + return Parent::getAttribute(2); + } + + const FReal* getForcesX() const { + return Parent::getAttribute(2); + } + + FReal* getForcesY(){ + return Parent::getAttribute(3); + } + + const FReal* getForcesY() const { + return Parent::getAttribute(3); + } + + FReal* getForcesZ(){ + return Parent::getAttribute(4); + } + + const FReal* getForcesZ() const { + return Parent::getAttribute(4); + } +}; + +#endif // FROTATIONLPARTICLECONTAINER_HPP diff --git a/Src/Kernels/Spherical/FAbstractSphericalKernel.hpp b/Src/Kernels/Spherical/FAbstractSphericalKernel.hpp index 1524597ea..976040193 100755 --- a/Src/Kernels/Spherical/FAbstractSphericalKernel.hpp +++ b/Src/Kernels/Spherical/FAbstractSphericalKernel.hpp @@ -22,17 +22,20 @@ #include "../../Utils/FTrace.hpp" #include "../../Utils/FMemUtils.hpp" #include "../../Utils/FSmartPointer.hpp" +#include "../../Utils/FPoint.hpp" #include "../../Containers/FTreeCoordinate.hpp" +#include "../P2P/FP2P.hpp" + #include "FHarmonic.hpp" /** * @author Berenger Bramas (berenger.bramas@inria.fr) * This is the abstract spherical harmonic kernel */ -template< class ParticleClass, class CellClass, class ContainerClass> -class FAbstractSphericalKernel : public FAbstractKernels<ParticleClass,CellClass,ContainerClass> { +template< class CellClass, class ContainerClass> +class FAbstractSphericalKernel : public FAbstractKernels<CellClass,ContainerClass> { protected: const int devP; //< The P const FReal boxWidth; //< the box width at leaf level @@ -144,11 +147,15 @@ public: // Copying the position is faster than using cell position const FPoint polePosition = getLeafCenter(inPole->getCoordinate()); // For all particles in the leaf box - typename ContainerClass::ConstBasicIterator iterParticle(*inParticles); - while( iterParticle.hasNotFinished()){ + const FReal*const physicalValues = inParticles->getPhysicalValues(); + const FReal*const positionsX = inParticles->getPositions()[0]; + const FReal*const positionsY = inParticles->getPositions()[1]; + const FReal*const positionsZ = inParticles->getPositions()[2]; + for(int idxPart = 0 ; idxPart < inParticles->getNbParticles() ; ++idxPart){ // P2M - particleToMultiPole(cellMultiPole, polePosition, iterParticle.data()); - iterParticle.gotoNext(); + particleToMultiPole(cellMultiPole, polePosition, + FPoint(positionsX[idxPart],positionsY[idxPart],positionsZ[idxPart]), + physicalValues[idxPart]); } } @@ -163,31 +170,6 @@ public: } } } - // Just for check purpose - void ocM2M(CellClass* const FRestrict inPole, const CellClass *const FRestrict *const FRestrict inChild, const int inLevel) { - FComplexe* FRestrict const multipole_exp_target = inPole->getMultipole(); - // iter on each child and process M2M - // Reset to zero - // - std::cout << std::endl<<"Multipole value to found" <<std::endl; - for(int idxPole = 0 ; idxPole < inPole->GetPoleSize() ; ++idxPole){ - std::cout << " "<< multipole_exp_target[idxPole] ; - multipole_exp_target[idxPole] = FComplexe(0.0,0.0); - } - std::cout <<std::endl; -// - const FComplexe* FRestrict const preM2MTransitionsAtLevel = preM2MTransitions[inLevel]; - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - if(inChild[idxChild]){ - multipoleToMultipole(multipole_exp_target, inChild[idxChild]->getMultipole(), &preM2MTransitionsAtLevel[idxChild * harmonic.getExpSize()]); - std::cout << "Add multipole from child "<< idxChild << std::endl; - for(int idxPole = 0 ; idxPole < inPole->GetPoleSize() ; ++idxPole){ - std::cout << " "<< multipole_exp_target[idxPole] ; - } - std::cout <<std::endl; - } - } - } /** M2L with a cell and all the existing neighbors */ virtual void M2L(CellClass* const FRestrict pole, const CellClass* distantNeighbors[343], @@ -205,16 +187,25 @@ public: } /** L2P with a cell and all its particles */ - void L2P(const CellClass* const local, ContainerClass* const particles){ + void L2P(const CellClass* const local, ContainerClass* const inParticles){ const FComplexe* const cellLocal = local->getLocal(); // Copying the position is faster than using cell position const FPoint localPosition = getLeafCenter(local->getCoordinate()); // For all particles in the leaf box - typename ContainerClass::BasicIterator iterTarget(*particles); - while( iterTarget.hasNotFinished() ){ + const FReal*const physicalValues = inParticles->getPhysicalValues(); + const FReal*const positionsX = inParticles->getPositions()[0]; + const FReal*const positionsY = inParticles->getPositions()[1]; + const FReal*const positionsZ = inParticles->getPositions()[2]; + FReal*const potentials = inParticles->getPotentials(); + FReal*const forcesX = inParticles->getForcesX(); + FReal*const forcesY = inParticles->getForcesY(); + FReal*const forcesZ = inParticles->getForcesZ(); + for(int idxPart = 0 ; idxPart < inParticles->getNbParticles() ; ++idxPart){ // L2P - localToParticle(&iterTarget.data(), localPosition, cellLocal); - iterTarget.gotoNext(); + localToParticle(localPosition, cellLocal, + FPoint(positionsX[idxPart],positionsY[idxPart],positionsZ[idxPart]), + physicalValues[idxPart], &potentials[idxPart], + &forcesX[idxPart],&forcesY[idxPart],&forcesZ[idxPart]); } } @@ -229,85 +220,7 @@ public: void P2P(const FTreeCoordinate& inLeafPosition, ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict sources, ContainerClass* const directNeighborsParticles[27], const int /*size*/){ - - const bool isNotTsm = (targets != sources); - if( isNotTsm ) { // Compute interaction in this leaf - { - typename ContainerClass::BasicIterator iterTarget(*targets); - while( iterTarget.hasNotFinished() ){ - // We copy the target particle to work with a particle in the heap - ParticleClass target( iterTarget.data() ); - - // For all the source particles in the same leaf - typename ContainerClass::ConstBasicIterator iterSameBox(*sources); - while( iterSameBox.hasNotFinished() ){ - directInteraction(&target, iterSameBox.data()); - iterSameBox.gotoNext(); - } - // Set data and progress - iterTarget.setData(target); - iterTarget.gotoNext(); - } - } - // For all the neigbors leaves - for(int idxDirectNeighbors = 0 ; idxDirectNeighbors < 27 ; ++idxDirectNeighbors){ - if( directNeighborsParticles[idxDirectNeighbors] ){ - // For all particles in current leaf - typename ContainerClass::BasicIterator iterTarget(*targets); - while( iterTarget.hasNotFinished() ){ - ParticleClass target( iterTarget.data() ); - // For all the particles in the other leaf - typename ContainerClass::ConstBasicIterator iterSource(*directNeighborsParticles[idxDirectNeighbors]); - while( iterSource.hasNotFinished() ){ - directInteraction(&target, iterSource.data()); - iterSource.gotoNext(); - } - // Set data and progress - iterTarget.setData(target); - iterTarget.gotoNext(); - } - } - } - } - else { // Compute interaction in this leaf - { - typename ContainerClass::BasicIterator iterTarget(*targets); - while( iterTarget.hasNotFinished() ){ - // We copy the target particle to work with a particle in the heap - ParticleClass target( iterTarget.data() ); - - // For all particles after the current one - typename ContainerClass::BasicIterator iterSameBox = iterTarget; - iterSameBox.gotoNext(); - while( iterSameBox.hasNotFinished() ){ - directInteractionMutual(&target, &iterSameBox.data()); - iterSameBox.gotoNext(); - } - // Set data and progress - iterTarget.setData(target); - iterTarget.gotoNext(); - } - } - // For all the neigbors leaves - for(int idxDirectNeighbors = 0 ; idxDirectNeighbors <= 13 ; ++idxDirectNeighbors){ - if( directNeighborsParticles[idxDirectNeighbors] ){ - // For all particles in current leaf - typename ContainerClass::BasicIterator iterTarget(*targets); - while( iterTarget.hasNotFinished() ){ - ParticleClass target( iterTarget.data() ); - // For all the particles in the other leaf - typename ContainerClass::BasicIterator iterSource(*directNeighborsParticles[idxDirectNeighbors]); - while( iterSource.hasNotFinished() ){ - directInteractionMutual(&target, &iterSource.data()); - iterSource.gotoNext(); - } - // Set data and progress - iterTarget.setData(target); - iterTarget.gotoNext(); - } - } - } - } + FP2P::FullMutual(targets,directNeighborsParticles,14); } /** This P2P has to be used when target != sources @@ -321,26 +234,7 @@ public: void P2PRemote(const FTreeCoordinate& , ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict , ContainerClass* const directNeighborsParticles[27], const int /*size*/){ - // TODO manage for periodic - for(int idxDirectNeighbors = 0 ; idxDirectNeighbors < 27 ; ++idxDirectNeighbors){ - if( directNeighborsParticles[idxDirectNeighbors] ){ - // For all particles in current leaf - typename ContainerClass::BasicIterator iterTarget(*targets); - while( iterTarget.hasNotFinished() ){ - ParticleClass target( iterTarget.data() ); - // For all the particles in the other leaf - typename ContainerClass::BasicIterator iterSource(*directNeighborsParticles[idxDirectNeighbors]); - while( iterSource.hasNotFinished() ){ - directInteraction(&target, iterSource.data()); - - iterSource.gotoNext(); - } - // Set data and progress - iterTarget.setData(target); - iterTarget.gotoNext(); - } - } - } + FP2P::FullRemote(targets,directNeighborsParticles,27); } private: @@ -370,13 +264,13 @@ private: * */ void particleToMultiPole(FComplexe* const cellMultiPole, const FPoint& inPolePosition , - const ParticleClass& particle){ + const FPoint& particlePosition, const FReal particlePhysicalValue){ // Inner of Qi - Z0 => harmonic.result - harmonic.computeInner( FSpherical(particle.getPosition() - inPolePosition) ); + harmonic.computeInner( FSpherical(particlePosition - inPolePosition) ); FReal minus_one_pow_j = 1.0; // (-1)^j => be in turn 1 and -1 - const FReal qParticle = particle.getPhysicalValue(); // q in the formula + const FReal qParticle = particlePhysicalValue; // q in the formula int index_j_k = 0; // p_exp_term & p_Y_term // J from 0 to P @@ -584,15 +478,17 @@ private: /** L2P */ - void localToParticle(ParticleClass*const particle, const FPoint& local_position, - const FComplexe*const local_exp){ + void localToParticle(const FPoint& local_position,const FComplexe*const local_exp, + const FPoint& particlePosition, + const FReal physicalValue, FReal*const potential, + FReal*const forcesX,FReal*const forcesY,FReal*const forcesZ){ //--------------- Forces ----------------// FReal force_vector_in_local_base_x = 0; FReal force_vector_in_local_base_y = 0; FReal force_vector_in_local_base_z = 0; - const FSpherical spherical(particle->getPosition() - local_position); + const FSpherical spherical(particlePosition - local_position); harmonic.computeInnerTheta( spherical ); int index_j_k = 1; @@ -705,12 +601,13 @@ private: cos_theta * force_vector_in_local_base_x + (-sin_theta) * force_vector_in_local_base_y); - const FReal physicalValue = particle->getPhysicalValue(); force_vector_tmp_x *= physicalValue; force_vector_tmp_y *= physicalValue; force_vector_tmp_z *= physicalValue; - particle->incForces( force_vector_tmp_x, force_vector_tmp_y, force_vector_tmp_z ); + (*forcesX) += force_vector_tmp_x; + (*forcesY) += force_vector_tmp_y; + (*forcesZ) += force_vector_tmp_z; //--------------- Potential ----------------// @@ -731,84 +628,48 @@ private: } } - particle->incPotential(result /* * physicalValue*/); - + (*potential) += (result /* * physicalValue*/); } public: - /** P2P mutual interaction - * F = q * q' / r² - */ - void directInteractionMutual(ParticleClass*const FRestrict target, ParticleClass*const FRestrict source){ - - FReal dx = source->getPosition().getX() - target->getPosition().getX(); - FReal dy = source->getPosition().getY() - target->getPosition().getY(); - FReal dz = source->getPosition().getZ() - target->getPosition().getZ(); - - FReal inv_square_distance = FReal(1.0) / (dx*dx + dy*dy + dz*dz); - FReal inv_distance = FMath::Sqrt(inv_square_distance); - - inv_square_distance *= inv_distance; - inv_square_distance *= target->getPhysicalValue() * source->getPhysicalValue(); - - dx *= inv_square_distance; - dy *= inv_square_distance; - dz *= inv_square_distance; - - target->incForces( dx, dy, dz); - target->incPotential( inv_distance * source->getPhysicalValue() ); - - source->incForces( (-dx), (-dy), (-dz)); - source->incPotential( inv_distance * target->getPhysicalValue() ); - - } - - /** P2P NO mutual interaction - * F = q * q' / r² - */ - void directInteraction(ParticleClass*const FRestrict target, const ParticleClass& source){ - - FReal dx = source.getPosition().getX() - target->getPosition().getX(); - FReal dy = source.getPosition().getY() - target->getPosition().getY(); - FReal dz = source.getPosition().getZ() - target->getPosition().getZ(); - - FReal inv_square_distance = FReal(1.0) / (dx*dx + dy*dy + dz*dz); - FReal inv_distance = FMath::Sqrt(inv_square_distance); - - inv_square_distance *= inv_distance; - inv_square_distance *= target->getPhysicalValue() * source.getPhysicalValue(); - - dx *= inv_square_distance; - dy *= inv_square_distance; - dz *= inv_square_distance; - - target->incForces( dx, dy, dz); - target->incPotential( inv_distance * source.getPhysicalValue() ); - - } - - /** Update a velocity of a particle * */ - void computeVelocity(ParticleClass*const FRestrict target, const FReal DT){ - const FReal physicalValue = target->getPhysicalValue(); - // Coef = 1/m * time/2 - const FReal coef = (FReal(1.0)/physicalValue) * (DT/FReal(2.0)); - - // velocity = velocity + forces * coef - FPoint forces_coef(target->getForces()); - forces_coef *= coef; - target->incVelocity(forces_coef); + void computeVelocity(ContainerClass*const FRestrict inParticles, const FReal DT){ + const FReal*const physicalValues = inParticles->getPhysicalValues(); + FReal*const forcesX = inParticles->getForcesX(); + FReal*const forcesY = inParticles->getForcesY(); + FReal*const forcesZ = inParticles->getForcesZ(); + FVector<FPoint>& velocities = inParticles->getVelocities(); + + for(int idxPart = 0 ; idxPart < inParticles->getNbParticles() ; ++idxPart){ + const FReal physicalValue = physicalValues[idxPart]; + // Coef = 1/m * time/2 + const FReal coef = (FReal(1.0)/physicalValue) * (DT/FReal(2.0)); + + // velocity = velocity + forces * coef + FPoint forces_coef(forcesX[idxPart], forcesY[idxPart], forcesZ[idxPart]); + forces_coef *= coef; + velocities[idxPart] += (forces_coef); + } } /** Update a position of a particle * */ - void updatePosition(ParticleClass*const FRestrict target, const FReal DT){ - FPoint velocity_dt( target->getVelocity() ); - velocity_dt *= DT; - target->incPosition( velocity_dt ); + void updatePosition(ContainerClass*const FRestrict inParticles, const FReal DT){ + FReal*const positionsX = inParticles->getWPositions()[0]; + FReal*const positionsY = inParticles->getWPositions()[1]; + FReal*const positionsZ = inParticles->getWPositions()[2]; + FVector<FPoint>& velocities = inParticles->getVelocities(); + + for(int idxPart = 0 ; idxPart < inParticles->getNbParticles() ; ++idxPart){ + FPoint velocity_dt( velocities[idxPart] ); + velocity_dt *= DT; + positionsX[idxPart] += velocity_dt.getX(); + positionsY[idxPart] += velocity_dt.getY(); + positionsZ[idxPart] += velocity_dt.getZ(); + } } }; diff --git a/Src/Kernels/Spherical/FSphericalBlasKernel.hpp b/Src/Kernels/Spherical/FSphericalBlasKernel.hpp index 3249cc01e..3afa3266b 100755 --- a/Src/Kernels/Spherical/FSphericalBlasKernel.hpp +++ b/Src/Kernels/Spherical/FSphericalBlasKernel.hpp @@ -25,10 +25,10 @@ * @author Berenger Bramas (berenger.bramas@inria.fr) * This class is a spherical harmonic kernels using blas */ -template< class ParticleClass, class CellClass, class ContainerClass> -class FSphericalBlasKernel : public FAbstractSphericalKernel<ParticleClass,CellClass,ContainerClass> { +template< class CellClass, class ContainerClass> +class FSphericalBlasKernel : public FAbstractSphericalKernel<CellClass,ContainerClass> { protected: - typedef FAbstractSphericalKernel<ParticleClass,CellClass,ContainerClass> Parent; + typedef FAbstractSphericalKernel<CellClass,ContainerClass> Parent; const int FF_MATRIX_ROW_DIM; //< The blas matrix number of rows const int FF_MATRIX_COLUMN_DIM; //< The blas matrix number of columns diff --git a/Src/Kernels/Spherical/FSphericalBlockBlasKernel.hpp b/Src/Kernels/Spherical/FSphericalBlockBlasKernel.hpp index d91768e85..c9ed1026f 100755 --- a/Src/Kernels/Spherical/FSphericalBlockBlasKernel.hpp +++ b/Src/Kernels/Spherical/FSphericalBlockBlasKernel.hpp @@ -26,10 +26,10 @@ * @author Berenger Bramas (berenger.bramas@inria.fr) * This class is a spherical harmonic kernels using block blas */ -template< class ParticleClass, class CellClass, class ContainerClass> -class FSphericalBlockBlasKernel : public FAbstractSphericalKernel<ParticleClass,CellClass,ContainerClass> { +template< class CellClass, class ContainerClass> +class FSphericalBlockBlasKernel : public FAbstractSphericalKernel<CellClass,ContainerClass> { protected: - typedef FAbstractSphericalKernel<ParticleClass,CellClass,ContainerClass> Parent; + typedef FAbstractSphericalKernel<CellClass,ContainerClass> Parent; /** A interaction properties */ struct ComputationPair { diff --git a/Src/Kernels/Spherical/FSphericalKernel.hpp b/Src/Kernels/Spherical/FSphericalKernel.hpp index d8ed3430e..adeb9a1cf 100755 --- a/Src/Kernels/Spherical/FSphericalKernel.hpp +++ b/Src/Kernels/Spherical/FSphericalKernel.hpp @@ -23,10 +23,10 @@ * @author Berenger Bramas (berenger.bramas@inria.fr) * This class is the basic spherical harmonic kernel */ -template< class ParticleClass, class CellClass, class ContainerClass> -class FSphericalKernel : public FAbstractSphericalKernel<ParticleClass,CellClass,ContainerClass> { +template< class CellClass, class ContainerClass> +class FSphericalKernel : public FAbstractSphericalKernel<CellClass,ContainerClass> { protected: - typedef FAbstractSphericalKernel<ParticleClass,CellClass,ContainerClass> Parent; + typedef FAbstractSphericalKernel<CellClass,ContainerClass> Parent; const int devM2lP; //< A secondary P diff --git a/Src/Kernels/Spherical/FSphericalParticle.hpp b/Src/Kernels/Spherical/FSphericalParticle.hpp deleted file mode 100755 index 18ac97be6..000000000 --- a/Src/Kernels/Spherical/FSphericalParticle.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== -#ifndef FSPHERICALPARTICLE_HPP -#define FSPHERICALPARTICLE_HPP - -#include "../../Extensions/FExtendForces.hpp" -#include "../../Extensions/FExtendPotential.hpp" -#include "../../Extensions/FExtendParticleType.hpp" -#include "../../Components/FFmaParticle.hpp" - -#include "../../Components/FAbstractSerializable.hpp" - -class FSphericalParticle : public FExtendForces, public FFmaParticle, public FExtendPotential { -public: - - /** Save current object */ - void save(FBufferWriter& buffer) const { - FExtendForces::save(buffer); - FFmaParticle::save(buffer); - FExtendPotential::save(buffer); - } - /** Retrieve current object */ - void restore(FBufferReader& buffer) { - FExtendForces::restore(buffer); - FFmaParticle::restore(buffer); - FExtendPotential::restore(buffer); - } -}; - - -class FTypedSphericalParticle : public FSphericalParticle, public FExtendParticleType { -public: - /** Save current object */ - void save(FBufferWriter& buffer) const { - FSphericalParticle::save(buffer); - FExtendParticleType::save(buffer); - } - /** Retrieve current object */ - void restore(FBufferReader& buffer) { - FSphericalParticle::restore(buffer); - FExtendParticleType::restore(buffer); - } -}; - -#endif // FSPHERICALPARTICLE_HPP diff --git a/Src/Kernels/Spherical/FSphericalRotationKernel.hpp b/Src/Kernels/Spherical/FSphericalRotationKernel.hpp index 97781c95c..700f54e73 100755 --- a/Src/Kernels/Spherical/FSphericalRotationKernel.hpp +++ b/Src/Kernels/Spherical/FSphericalRotationKernel.hpp @@ -23,10 +23,10 @@ * @author Berenger Bramas (berenger.bramas@inria.fr) * This class is the rotation spherical harmonic kernel */ -template< class ParticleClass, class CellClass, class ContainerClass> -class FSphericalRotationKernel : public FAbstractSphericalKernel<ParticleClass,CellClass,ContainerClass> { +template< class CellClass, class ContainerClass> +class FSphericalRotationKernel : public FAbstractSphericalKernel<CellClass,ContainerClass> { protected: - typedef FAbstractSphericalKernel<ParticleClass,CellClass,ContainerClass> Parent; + typedef FAbstractSphericalKernel<CellClass,ContainerClass> Parent; /** This class define some information to use rotation computation */ diff --git a/Tests/Kernels/testChebAlgorithm.cpp b/Tests/Kernels/testChebAlgorithm.cpp index 524e9efa3..7e16983b1 100755 --- a/Tests/Kernels/testChebAlgorithm.cpp +++ b/Tests/Kernels/testChebAlgorithm.cpp @@ -26,13 +26,15 @@ #include "../../Src/Files/FFmaScanfLoader.hpp" #include "../../Src/Files/FFmaBinLoader.hpp" -#include "../../Src/Kernels/Chebyshev/FChebParticle.hpp" #include "../../Src/Kernels/Chebyshev/FChebLeaf.hpp" #include "../../Src/Kernels/Chebyshev/FChebCell.hpp" #include "../../Src/Kernels/Chebyshev/FChebMatrixKernel.hpp" #include "../../Src/Kernels/Chebyshev/FChebKernel.hpp" #include "../../Src/Kernels/Chebyshev/FChebSymKernel.hpp" +#include "../../Src/Components/FSimpleLeaf.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" + #include "../../Src/Utils/FParameters.hpp" #include "../../Src/Utils/FMemUtils.hpp" @@ -87,25 +89,24 @@ int main(int argc, char* argv[]) FTic time; - // typedefs - typedef FChebParticle ParticleClass; - typedef FVector<FChebParticle> ContainerClass; - typedef FChebLeaf<ParticleClass,ContainerClass> LeafClass; + // typedefs + typedef FP2PParticleContainer ContainerClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; //typedef FChebMatrixKernelLJ MatrixKernelClass; typedef FChebMatrixKernelR MatrixKernelClass; typedef FChebCell<ORDER> CellClass; - typedef FOctree<ParticleClass,CellClass,ContainerClass,LeafClass> OctreeClass; + typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; //typedef FChebKernel<ParticleClass,CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; - typedef FChebSymKernel<ParticleClass,CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; + typedef FChebSymKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; //typedef FFmmAlgorithm<OctreeClass,ParticleClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; - typedef FFmmAlgorithmThread<OctreeClass,ParticleClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; + typedef FFmmAlgorithmThread<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; // What we do ////////////////////////////////////////////////////// std::cout << ">> Testing the Chebyshev interpolation base FMM algorithm.\n"; // open particle file - FFmaScanfLoader<ParticleClass> loader(filename); + FFmaScanfLoader loader(filename); //FFmaBinLoader<ParticleClass> loader(filename); if(!loader.isOpen()) throw std::runtime_error("Particle file couldn't be opened!"); @@ -117,7 +118,16 @@ int main(int argc, char* argv[]) << " particles in a octree of height " << TreeHeight << " ..." << std::endl; time.tic(); - loader.fillTree(tree); + + { + FPoint particlePosition; + FReal physicalValue = 0.0; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition, physicalValue); + } + } + std::cout << "Done " << "(" << time.tacAndElapsed() << ")." << std::endl; // ----------------------------------------------------- @@ -208,7 +218,7 @@ int main(int argc, char* argv[]) // ----------------------------------------------------- // find first non empty leaf cell - if (FParameters::findParameter(argc,argv,"-dont_check_accuracy") == FParameters::NotFound) { + /*if (FParameters::findParameter(argc,argv,"-dont_check_accuracy") == FParameters::NotFound) { OctreeClass::Iterator iLeafs(&tree); iLeafs.gotoBottomLeft(); @@ -298,7 +308,7 @@ int main(int argc, char* argv[]) delete [] ApproxPotential; delete [] Force; delete [] ApproxForce; - } + }*/ /* // Check if particles are strictly within its containing cells diff --git a/Tests/Kernels/testCompareKernels.cpp b/Tests/Kernels/testCompareKernels.cpp index 4b050fb59..004dcebbd 100755 --- a/Tests/Kernels/testCompareKernels.cpp +++ b/Tests/Kernels/testCompareKernels.cpp @@ -35,7 +35,6 @@ #include "../../Src/Core/FFmmAlgorithmThread.hpp" // chebyshev kernel -#include "../../Src/Kernels/Chebyshev/FChebParticle.hpp" #include "../../Src/Kernels/Chebyshev/FChebLeaf.hpp" #include "../../Src/Kernels/Chebyshev/FChebCell.hpp" #include "../../Src/Kernels/Chebyshev/FChebMatrixKernel.hpp" @@ -43,14 +42,14 @@ #include "../../Src/Kernels/Chebyshev/FChebSymKernel.hpp" // spherical kernel -#include "../../Src/Components/FSimpleLeaf.hpp" #include "../../Src/Kernels/Spherical/FSphericalKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalBlasKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalBlockBlasKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalRotationKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" +#include "../../Src/Components/FSimpleLeaf.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" /** * This program compares two different kernels, eg., the Chebyshev kernel with @@ -85,86 +84,6 @@ FReal computeINFnorm(const unsigned int N, const FReal *const u, const FReal *co } -template <class OctreeClass, class MatrixKernelClass, class ContainerClass> -class DirectInteractionComputer -{ - - const MatrixKernelClass MatrixKernel; - -public: - DirectInteractionComputer() - : MatrixKernel() - {} - - unsigned int operator()(OctreeClass& tree, const unsigned int NumTargetCells, - FReal* &p, FReal* &f) const - { - // begin direct computation of first leaf cell - typename OctreeClass::Iterator iLeafs(&tree); - iLeafs.gotoBottomLeft(); - - const ContainerClass* *const TargetSets = new const ContainerClass* [NumTargetCells]; - - unsigned int n = 0; - for (unsigned int t=0; t<NumTargetCells; ++t) { - TargetSets[t] = iLeafs.getCurrentListTargets(); - n += TargetSets[t]->getSize(); - iLeafs.moveRight(); - } - p = new FReal [n]; - FBlas::setzero(n, p); - f = new FReal [n * 3]; - FBlas::setzero(n * 3, f); - - std::cout << "\nDirect computation of " << n << " target particles ..." << std::endl; - - unsigned int start = 0; - for (unsigned int t=0; t<NumTargetCells; ++t) { - iLeafs.gotoBottomLeft(); - - // retrieve targets - const ContainerClass *const Targets = TargetSets[t]; - - do { - const ContainerClass *const Sources = iLeafs.getCurrentListSrc(); - unsigned int counter = start; - typename ContainerClass::ConstBasicIterator iTarget(*Targets); - while(iTarget.hasNotFinished()) { - const FReal wt = iTarget.data().getPhysicalValue(); - typename ContainerClass::ConstBasicIterator iSource(*Sources); - while(iSource.hasNotFinished()) { - if (&iTarget.data() != &iSource.data()) { - const FReal ws = iSource.data().getPhysicalValue(); - const FReal one_over_r = MatrixKernel.evaluate(iTarget.data().getPosition(), - iSource.data().getPosition()); - // potential - p[counter] += one_over_r * ws; - // force - FPoint force(iSource.data().getPosition() - iTarget.data().getPosition()); - force *= ((ws*wt) * (one_over_r*one_over_r*one_over_r)); - f[counter*3 + 0] += force.getX(); - f[counter*3 + 1] += force.getY(); - f[counter*3 + 2] += force.getZ(); - } - iSource.gotoNext(); - } - counter++; - iTarget.gotoNext(); - } - } while(iLeafs.moveRight()); - - start += Targets->getSize(); - } - - delete [] TargetSets; - - return n; - } - -}; - - - // Simply create particles and try the kernels int main(int argc, char* argv[]) { @@ -172,20 +91,20 @@ int main(int argc, char* argv[]) const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); const unsigned int TreeHeight = FParameters::getValue(argc, argv, "-h", 5); const unsigned int SubTreeHeight = FParameters::getValue(argc, argv, "-sh", 2); - const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", 1); - - omp_set_num_threads(NbThreads); - - std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; - + const unsigned int NbThreads = FParameters::getValue(argc, argv, "-t", omp_get_max_threads()); + + omp_set_num_threads(NbThreads); + + std::cout << "\n>> Using " << omp_get_max_threads() << " threads.\n" << std::endl; + // init timer FTic time; - // only for direct computation of nt1 target particles - unsigned int nt1 = 0; - FReal* p10; p10 = NULL; - FReal* f10; p10 = NULL; - + // only for direct computation of nt1 target particles + unsigned int nt1 = 0; + FReal* p10; p10 = NULL; + FReal* f10; p10 = NULL; + //////////////////////////////////////////////////////////////////// { // begin Chebyshef kernel @@ -197,21 +116,20 @@ int main(int argc, char* argv[]) FReal* f1; p1 = NULL; // typedefs - typedef FChebParticle ParticleClass; - typedef FVector<FChebParticle> ContainerClass; - typedef FChebLeaf<ParticleClass,ContainerClass> LeafClass; + typedef FP2PParticleContainer ContainerClass; + typedef FSimpleLeaf<ContainerClass> LeafClass; typedef FChebMatrixKernelR MatrixKernelClass; typedef FChebCell<ORDER> CellClass; - typedef FOctree<ParticleClass,CellClass,ContainerClass,LeafClass> OctreeClass; + typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; - //typedef FChebKernel<ParticleClass,CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; - typedef FChebSymKernel<ParticleClass,CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; - //typedef FFmmAlgorithm<OctreeClass,ParticleClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; - typedef FFmmAlgorithmThread<OctreeClass,ParticleClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; + //typedef FChebKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; + typedef FChebSymKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; + //typedef FFmmAlgorithm<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; + typedef FFmmAlgorithmThread<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; // open particle file - FFmaScanfLoader<ParticleClass> loader(filename); + FFmaScanfLoader loader(filename); if(!loader.isOpen()) throw std::runtime_error("Particle file couldn't be opened!"); // init oct-tree @@ -219,13 +137,20 @@ int main(int argc, char* argv[]) { // ----------------------------------------------------- std::cout << "Creating & Inserting " << loader.getNumberOfParticles() - << " particles ..." << std::endl; + << " particles ..." << std::endl; std::cout << "\tHeight : " << TreeHeight << " \t sub-height : " << SubTreeHeight << std::endl; time.tic(); - loader.fillTree(tree); + + FPoint particlePosition; + FReal physicalValue = 0.0; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition, physicalValue); + } + time.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " - << time.elapsed() << "s)." << std::endl; + << time.elapsed() << "s)." << std::endl; } // ----------------------------------------------------- { // ----------------------------------------------------- @@ -238,7 +163,7 @@ int main(int argc, char* argv[]) std::cout << "Done " << "(@Algorithm = " << time.elapsed() << "s)." << std::endl; } // ----------------------------------------------------- - { // ----------------------------------------------------- + /*{ // ----------------------------------------------------- // read potential from particles and write to array p1 p1 = new FReal [loader.getNumberOfParticles()]; f1 = new FReal [loader.getNumberOfParticles() * 3]; @@ -257,16 +182,12 @@ int main(int argc, char* argv[]) iTarget.gotoNext(); } } while(iLeafs.moveRight()); - } // ----------------------------------------------------- + } // -----------------------------------------------------*/ - // compute direct interaction - const unsigned int NumTargetCells = 3; - DirectInteractionComputer<OctreeClass,MatrixKernelClass,ContainerClass> direct; - nt1 = direct(tree, NumTargetCells, p10, f10); - - - // for (unsigned int n=0; n<nt1; ++n) - // std::cout << p10[n] << " - " << p1[n] << " = " << p10[n]-p1[n] << std::endl; + // compute direct interaction + const unsigned int NumTargetCells = 3; + //DirectInteractionComputer<OctreeClass,MatrixKernelClass,ContainerClass> direct; + //nt1 = direct(tree, NumTargetCells, p10, f10); std::cout << "\nPotential error:" << std::endl; std::cout << "Relative L2 error = " << computeL2norm( nt1, p10, p1) << std::endl; @@ -290,21 +211,20 @@ int main(int argc, char* argv[]) const int DevP = FParameters::getValue(argc, argv, "-p", 5); // typedefs - typedef FSphericalParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - //typedef FSphericalBlasKernel<ParticleClass, CellClass, ContainerClass > KernelClass; - //typedef FSphericalBlockBlasKernel<ParticleClass, CellClass, ContainerClass > KernelClass; - //typedef FSphericalKernel<ParticleClass, CellClass, ContainerClass > KernelClass; - typedef FSphericalBlockBlasKernel<ParticleClass, CellClass, ContainerClass > KernelClass; - //typedef FSphericalRotationKernel<ParticleClass, CellClass, ContainerClass > KernelClass; - //typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - typedef FFmmAlgorithmThread<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FP2PParticleContainer ContainerClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + //typedef FSphericalBlasKernel< CellClass, ContainerClass > KernelClass; + //typedef FSphericalBlockBlasKernel< CellClass, ContainerClass > KernelClass; + //typedef FSphericalKernel< CellClass, ContainerClass > KernelClass; + typedef FSphericalBlockBlasKernel< CellClass, ContainerClass > KernelClass; + //typedef FSphericalRotationKernel< CellClass, ContainerClass > KernelClass; + //typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; // open particle file - FFmaScanfLoader<ParticleClass> loader(filename); + FFmaScanfLoader loader(filename); if(!loader.isOpen()) throw std::runtime_error("Particle file couldn't be opened!"); // init cell class and oct-tree @@ -314,14 +234,21 @@ int main(int argc, char* argv[]) { // ----------------------------------------------------- std::cout << "Creating & Inserting " << loader.getNumberOfParticles() - << " particles ..." << std::endl; + << " particles ..." << std::endl; std::cout << "\tHeight : " << TreeHeight << " \t sub-height : " - << SubTreeHeight << std::endl; + << SubTreeHeight << std::endl; time.tic(); - loader.fillTree(tree); + + FPoint particlePosition; + FReal physicalValue = 0.0; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition, physicalValue); + } + time.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " - << time.elapsed() << "s)." << std::endl; + << time.elapsed() << "s)." << std::endl; } // ----------------------------------------------------- // ----------------------------------------------------- @@ -336,7 +263,7 @@ int main(int argc, char* argv[]) FReal*const fmmParticlesPotential = new FReal[loader.getNumberOfParticles()]; FReal*const fmmParticlesForces = new FReal [loader.getNumberOfParticles() * 3]; - { // ----------------------------------------------------- + /*{ // ----------------------------------------------------- // read potential from particles and write to array p2 OctreeClass::Iterator leavesIterator(&tree); leavesIterator.gotoBottomLeft(); @@ -357,19 +284,19 @@ int main(int argc, char* argv[]) particlesIterator.gotoNext(); } } while(leavesIterator.moveRight()); - } // ----------------------------------------------------- + } // -----------------------------------------------------*/ std::cout << "\nPotential error:" << std::endl; std::cout << "Relative L2 error = " - << computeL2norm( nt1, p10, fmmParticlesPotential) << std::endl; + << computeL2norm( nt1, p10, fmmParticlesPotential) << std::endl; std::cout << "Relative Lmax error = " - << computeINFnorm(nt1, p10, fmmParticlesPotential) << std::endl; + << computeINFnorm(nt1, p10, fmmParticlesPotential) << std::endl; std::cout << "\nForces error:" << std::endl; std::cout << "Relative L2 error = " - << computeL2norm( nt1*3, f10, fmmParticlesForces) << std::endl; + << computeL2norm( nt1*3, f10, fmmParticlesForces) << std::endl; std::cout << "Relative Lmax error = " - << computeINFnorm(nt1*3, f10, fmmParticlesForces) << std::endl; + << computeINFnorm(nt1*3, f10, fmmParticlesForces) << std::endl; @@ -379,109 +306,9 @@ int main(int argc, char* argv[]) } // end FFmaBlas kernel - // free memory - if (p10!=NULL) delete [] p10; - if (f10!=NULL) delete [] f10; + // free memory + if (p10!=NULL) delete [] p10; + if (f10!=NULL) delete [] f10; return 0; } - - - - - - - -/* -// Check if particles are strictly within its containing cells -const FReal BoxWidthLeaf = BoxWidth / FReal(FMath::pow(2, TreeHeight-1)); -OctreeClass::Iterator octreeIterator(&tree); -octreeIterator.gotoBottomLeft(); -do{ -const CellClass *const LeafCell = octreeIterator.getCurrentCell(); -const FPoint& LeafCellCenter = LeafCell -> getPosition(); -const ContainerClass *const Particles = octreeIterator.getCurrentListSrc(); -ContainerClass::ConstBasicIterator particleIterator(*Particles); -while(particleIterator.hasNotFinished()) { -const FPoint distance(LeafCellCenter-particleIterator.data().getPosition()); -std::cout << "center - particle = " << distance << " < " << BoxWidthLeaf/FReal(2.) << std::endl; -if (std::abs(distance.getX())>BoxWidthLeaf/FReal(2.) || -std::abs(distance.getY())>BoxWidthLeaf/FReal(2.) || -std::abs(distance.getZ())>BoxWidthLeaf/FReal(2.)) { -std::cout << "stop" << std::endl; -exit(-1); -} -particleIterator.gotoNext(); -} -} while(octreeIterator.moveRight()); -*/ - - - - - - - - //unsigned int sizeFirstLeaf = 0; - //FReal* firstLeafPotential = 0; - //FReal* firstLeafForces = 0; - //{ // ----------------------------------------------------- - // // begin direct computation of first leaf cell - // OctreeClass::Iterator leavesIterator(&tree); - // leavesIterator.gotoBottomLeft(); - // ContainerClass *const firstLeaf = leavesIterator.getCurrentListTargets(); - // - // { // Compute the first leaf with it self - // ContainerClass::BasicIterator targetParticles(*firstLeaf); - // while(targetParticles.hasNotFinished()) { - // ContainerClass::ConstBasicIterator sourceParticles(*firstLeaf); - // while(sourceParticles.hasNotFinished()) { - // if (&targetParticles.data() != &sourceParticles.data()){ - // kernels.directInteraction( &targetParticles.data(), sourceParticles.data()); - // } - // sourceParticles.gotoNext(); - // } - // targetParticles.gotoNext(); - // } - // } - // - // while( leavesIterator.moveRight() ) { - // ContainerClass::ConstBasicIterator sourceParticles(*leavesIterator.getCurrentListSrc()); - // while(sourceParticles.hasNotFinished()) { - // ContainerClass::BasicIterator targetParticles(*firstLeaf); - // while(targetParticles.hasNotFinished()) { - // kernels.directInteraction( &targetParticles.data(), sourceParticles.data()); - // targetParticles.gotoNext(); - // } - // sourceParticles.gotoNext(); - // } - // } - // - // // Copy data - // sizeFirstLeaf = firstLeaf->getSize(); - // - // firstLeafPotential = new FReal[sizeFirstLeaf]; - // FBlas::setzero(sizeFirstLeaf, firstLeafPotential); - // - // firstLeafForces = new FReal[sizeFirstLeaf * 3]; - // FBlas::setzero(sizeFirstLeaf * 3, firstLeafForces); - // - // unsigned int particlePosition = 0; - // ContainerClass::ConstBasicIterator targetParticles(*firstLeaf); - // while(targetParticles.hasNotFinished()) { - // firstLeafPotential[particlePosition] = targetParticles.data().getPotential(); - // firstLeafForces[particlePosition*3 + 0] = targetParticles.data().getForces().getX(); - // firstLeafForces[particlePosition*3 + 1] = targetParticles.data().getForces().getY(); - // firstLeafForces[particlePosition*3 + 2] = targetParticles.data().getForces().getZ(); - // targetParticles.gotoNext(); - // ++particlePosition; - // } - //} // ----------------------------------------------------- - - //std::cout << "\nPotential error:" << std::endl; - //std::cout << "Relative L2 error = " << computeL2norm( sizeFirstLeaf, firstLeafPotential, fmmParticlesPotential) << std::endl; - //std::cout << "Relative Lmax error = " << computeINFnorm(sizeFirstLeaf, firstLeafPotential, fmmParticlesPotential) << std::endl; - // - //std::cout << "\nForces error:" << std::endl; - //std::cout << "Relative L2 error = " << computeL2norm( sizeFirstLeaf*3, firstLeafForces, fmmParticlesForces) << std::endl; - //std::cout << "Relative Lmax error = " << computeINFnorm(sizeFirstLeaf*3, firstLeafForces, fmmParticlesForces) << std::endl; diff --git a/Tests/Kernels/testFlopsChebAlgorithm.cpp b/Tests/Kernels/testFlopsChebAlgorithm.cpp index 5c1c7ef9d..420c9d144 100755 --- a/Tests/Kernels/testFlopsChebAlgorithm.cpp +++ b/Tests/Kernels/testFlopsChebAlgorithm.cpp @@ -26,8 +26,6 @@ #include "../../Src/Files/FFmaScanfLoader.hpp" #include "../../Src/Files/FFmaBinLoader.hpp" -#include "../../Src/Kernels/Chebyshev/FChebParticle.hpp" -#include "../../Src/Kernels/Chebyshev/FChebLeaf.hpp" #include "../../Src/Kernels/Chebyshev/FChebCell.hpp" #include "../../Src/Kernels/Chebyshev/FChebMatrixKernel.hpp" @@ -40,8 +38,8 @@ #include "../../Src/Core/FFmmAlgorithm.hpp" - - +#include "../../Src/Components/FSimpleLeaf.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" @@ -58,15 +56,14 @@ int main(int argc, char* argv[]) // init timer FTic time; - // typedefs - typedef FChebParticle ParticleClass; - typedef FVector<FChebParticle> ContainerClass; - typedef FChebLeaf<ParticleClass,ContainerClass> LeafClass; + // typedefs + typedef FP2PParticleContainer ContainerClass; + typedef FSimpleLeaf<ContainerClass> LeafClass; typedef FChebMatrixKernelR MatrixKernelClass; typedef FChebCell<ORDER> CellClass; - typedef FOctree<ParticleClass,CellClass,ContainerClass,LeafClass> OctreeClass; - typedef FChebFlopsSymKernel<ParticleClass,CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; - typedef FFmmAlgorithm<OctreeClass,ParticleClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; + typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; + typedef FChebFlopsSymKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; + typedef FFmmAlgorithm<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; // What we do ////////////////////////////////////////////////////// @@ -74,7 +71,7 @@ int main(int argc, char* argv[]) // open particle file //FFmaScanfLoader<ParticleClass> loader(filename); - FFmaBinLoader<ParticleClass> loader(filename); + FFmaBinLoader loader(filename); if(!loader.isOpen()) throw std::runtime_error("Particle file couldn't be opened!"); // init oct-tree @@ -84,7 +81,16 @@ int main(int argc, char* argv[]) std::cout << "Creating and inserting " << loader.getNumberOfParticles() << " particles in a octree of height " << TreeHeight << " ..." << std::endl; time.tic(); - loader.fillTree(tree); + + { + FPoint particlePosition; + FReal physicalValue = 0.0; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition, physicalValue); + } + } + std::cout << "Done " << "(" << time.tacAndElapsed() << ")." << std::endl; // ----------------------------------------------------- @@ -98,9 +104,6 @@ int main(int argc, char* argv[]) std::cout << "completed in " << time.tacAndElapsed() << "sec." << std::endl; // ----------------------------------------------------- - - - return 0; } diff --git a/Tests/Kernels/testRotationAlgorithm.cpp b/Tests/Kernels/testRotationAlgorithm.cpp index aae5de691..d32028b53 100755 --- a/Tests/Kernels/testRotationAlgorithm.cpp +++ b/Tests/Kernels/testRotationAlgorithm.cpp @@ -25,7 +25,7 @@ #include "../../Src/Core/FFmmAlgorithm.hpp" -#include "../../Src/Kernels/Rotation/FRotationParticle.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" #include "../../Src/Kernels/Rotation/FRotationKernel.hpp" #include "../../Src/Kernels/Rotation/FRotationCell.hpp" @@ -44,17 +44,16 @@ int main(int argc, char** argv){ static const int P = 9; - typedef FRotationParticle ParticleClass; typedef FRotationCell<P> CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainer ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FRotationKernel<ParticleClass, CellClass, ContainerClass , P> KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FRotationKernel< CellClass, ContainerClass , P> KernelClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - typedef FFmmAlgorithmThread<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassThread; - typedef FFmmAlgorithmTask<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassTask; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassThread; + typedef FFmmAlgorithmTask<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassTask; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test Spherical algorithm.\n"; std::cout << ">> You can pass -sequential or -task (thread by default).\n"; @@ -66,7 +65,7 @@ int main(int argc, char** argv){ std::cout << "Opening : " << filename << "\n"; - FFmaLoader<ParticleClass> loader(filename); + FFmaLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << " is missing\n"; return 1; @@ -82,7 +81,12 @@ int main(int argc, char** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - loader.fillTree(tree); + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint particlePosition; + FReal physicalValue; + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition, physicalValue ); + } counter.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; @@ -122,20 +126,24 @@ int main(int argc, char** argv){ { // get sum forces&potential FReal potential = 0; - FPoint forces; - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - do{ - ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets()); - while( iter.hasNotFinished() ){ - potential += iter.data().getPotential() * iter.data().getPhysicalValue(); - forces += iter.data().getForces(); - - iter.gotoNext(); + FReal fx = 0.0, fy = 0.0, fz = 0.0; + + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + potential += potentials[idxPart]; + fx += forcesX[idxPart]; + fy += forcesY[idxPart]; + fz += forcesZ[idxPart]; } - } while(octreeIterator.moveRight()); + }); - std::cout << "Foces Sum x = " << forces.getX() << " y = " << forces.getY() << " z = " << forces.getZ() << std::endl; + std::cout << "Foces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; std::cout << "Potential = " << potential << std::endl; } diff --git a/Tests/Kernels/testSphericalAlgorithm.cpp b/Tests/Kernels/testSphericalAlgorithm.cpp index 5c7f99c29..e3367ca20 100755 --- a/Tests/Kernels/testSphericalAlgorithm.cpp +++ b/Tests/Kernels/testSphericalAlgorithm.cpp @@ -31,11 +31,10 @@ #include "../../Src/Kernels/Spherical/FSphericalKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" #include "../../Src/Components/FSimpleLeaf.hpp" #include "../../Src/Files/FFmaLoader.hpp" - +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" /** This program show an example of use of * the fmm basic algo @@ -46,17 +45,16 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FSphericalParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainer ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FSphericalKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSphericalKernel< CellClass, ContainerClass > KernelClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - typedef FFmmAlgorithmThread<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassThread; - typedef FFmmAlgorithmTask<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassTask; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassThread; + typedef FFmmAlgorithmTask<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassTask; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test Spherical algorithm.\n"; std::cout << ">> You can pass -sequential or -task (thread by default).\n"; @@ -69,7 +67,7 @@ int main(int argc, char ** argv){ std::cout << "Opening : " << filename << "\n"; - FFmaLoader<ParticleClass> loader(filename); + FFmaLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << " is missing\n"; return 1; @@ -85,7 +83,12 @@ int main(int argc, char ** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - loader.fillTree(tree); + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint particlePosition; + FReal physicalValue; + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition, physicalValue ); + } counter.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; @@ -125,20 +128,24 @@ int main(int argc, char ** argv){ { // get sum forces&potential FReal potential = 0; - FPoint forces; - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - do{ - ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets()); - while( iter.hasNotFinished() ){ - potential += iter.data().getPotential() * iter.data().getPhysicalValue(); - forces += iter.data().getForces(); - - iter.gotoNext(); + FReal fx = 0.0, fy = 0.0, fz = 0.0; + + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + potential += potentials[idxPart]; + fx += forcesX[idxPart]; + fy += forcesY[idxPart]; + fz += forcesZ[idxPart]; } - } while(octreeIterator.moveRight()); + }); - std::cout << "Foces Sum x = " << forces.getX() << " y = " << forces.getY() << " z = " << forces.getZ() << std::endl; + std::cout << "Foces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; std::cout << "Potential = " << potential << std::endl; } diff --git a/Tests/Kernels/testSphericalBench.cpp b/Tests/Kernels/testSphericalBench.cpp index 46537e8ad..9c0e517f5 100755 --- a/Tests/Kernels/testSphericalBench.cpp +++ b/Tests/Kernels/testSphericalBench.cpp @@ -29,13 +29,12 @@ #include "../../Src/Kernels/Spherical/FSphericalKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" #include "../../Src/Components/FSimpleLeaf.hpp" #include "../../Src/Files/FFmaLoader.hpp" #include "../../Src/Files/FRandomLoader.hpp" - +#include "../../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp" /** This program show an example of use of * the fmm basic algo @@ -43,35 +42,27 @@ * related that each other */ -class IndexedParticle : public FSphericalParticle { - int index; -public: - IndexedParticle(): index(-1){} - - int getIndex() const{ - return index; - } - void setIndex( const int inIndex ){ - index = inIndex; - } +struct Particle{ + FPoint position; + FReal physicalValue; + FReal forces[3]; + FReal potential; }; - int restultIndex(const int idxP, const int idxH, const int minP, const int maxP, const int minH){ return (idxH-minH)*(maxP+1-minP)+(idxP-minP); } -typedef IndexedParticle ParticleClass; typedef FSphericalCell CellClass; -typedef FVector<ParticleClass> ContainerClass; +typedef FP2PParticleContainerIndexed ContainerClass; -typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; -typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; -typedef FSphericalKernel<ParticleClass, CellClass, ContainerClass > KernelClass; +typedef FSimpleLeaf< ContainerClass > LeafClass; +typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; +typedef FSphericalKernel< CellClass, ContainerClass > KernelClass; -typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; +typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; void doATest(const int NbParticles, const int minP, const int maxP, const int minH, const int maxH, @@ -79,28 +70,38 @@ void doATest(const int NbParticles, const int minP, const int maxP, const int mi FMath::FAccurater* allPotentialDiff, FReal* allAbsoluteDiff, FReal* timing, const int SizeSubLevels = 3, FReal* timeForDirect = 0){ FTic counter; - FRandomLoader<ParticleClass> loader(NbParticles); - ParticleClass*const particles = new ParticleClass[loader.getNumberOfParticles()]; + FRandomLoader loader(NbParticles); + + + + Particle*const particles = new Particle[loader.getNumberOfParticles()]; const bool computeDirectAndDiff = timeForDirect || allAbsoluteDiff || allPotentialDiff; { for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - loader.fillParticle(particles[idxPart]); - particles[idxPart].setIndex( idxPart ); + loader.fillParticle(&particles[idxPart].position); if((idxPart & 1) && neutral){ - particles[idxPart].setPhysicalValue( -physicalValue ); + particles[idxPart].physicalValue = -physicalValue; + } + else{ + particles[idxPart].physicalValue = physicalValue; } - else particles[idxPart].setPhysicalValue( physicalValue ); } // Compute direct if(computeDirectAndDiff){ printf("Compute direct!\n"); - KernelClass kernels(minP, minH, loader.getBoxWidth(), loader.getCenterOfBox()); counter.tic(); for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){ for(int idxOther = idxTarget + 1 ; idxOther < loader.getNumberOfParticles() ; ++idxOther){ - kernels.directInteractionMutual(&particles[idxTarget], &particles[idxOther]); + FP2P::MutualParticles(particles[idxTarget].position.getX(), particles[idxTarget].position.getY(), + particles[idxTarget].position.getZ(),particles[idxTarget].physicalValue, + &particles[idxTarget].forces[0],&particles[idxTarget].forces[1], + &particles[idxTarget].forces[2],&particles[idxTarget].potential, + particles[idxOther].position.getX(), particles[idxOther].position.getY(), + particles[idxOther].position.getZ(),particles[idxOther].physicalValue, + &particles[idxOther].forces[0],&particles[idxOther].forces[1], + &particles[idxOther].forces[2],&particles[idxOther].potential); } } if(timeForDirect) *timeForDirect = counter.tacAndElapsed(); @@ -123,10 +124,7 @@ void doATest(const int NbParticles, const int minP, const int maxP, const int mi counter.tic(); for(int idxPart = 0 ; idxPart < NbParticles ; ++idxPart){ - ParticleClass part = particles[idxPart]; - part.setPotential(0.0); - part.setForces(0.0,0.0,0.0); - tree.insert(part); + tree.insert(particles[idxPart].position, idxPart, particles[idxPart].physicalValue); } counter.tac(); @@ -160,29 +158,23 @@ void doATest(const int NbParticles, const int minP, const int maxP, const int mi FMath::FAccurater potentialDiff; FMath::FAccurater fx, fy, fz; FReal absoluteDiff = FReal(0.0); - { // Check that each particle has been summed with all other - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - do{ - ContainerClass::BasicIterator leafIter(*octreeIterator.getCurrentListTargets()); - - while( leafIter.hasNotFinished() ){ - const ParticleClass& other = particles[leafIter.data().getIndex()]; - - potentialDiff.add(other.getPotential(),leafIter.data().getPotential()); - absoluteDiff = FMath::Max(absoluteDiff,FMath::Abs(other.getPotential()-leafIter.data().getPotential())); - - fx.add(other.getForces().getX(),leafIter.data().getForces().getX()); - - fy.add(other.getForces().getY(),leafIter.data().getForces().getY()); - - fz.add(other.getForces().getZ(),leafIter.data().getForces().getZ()); - - leafIter.gotoNext(); - } - } while(octreeIterator.moveRight()); - } + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + const FVector<int>& indexes = leaf->getTargets()->getIndexes(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + const int indexPartOrig = indexes[idxPart]; + potentialDiff.add(particles[indexPartOrig].potential,potentials[idxPart]); + fx.add(particles[indexPartOrig].forces[0],forcesX[idxPart]); + fy.add(particles[indexPartOrig].forces[1],forcesY[idxPart]); + fz.add(particles[indexPartOrig].forces[2],forcesZ[idxPart]); + } + }); // Print for information printf("Potential diff is = %e \t %e\n",potentialDiff.getL2Norm(),potentialDiff.getInfNorm()); @@ -289,47 +281,50 @@ int main(int argc, char ** argv){ for(int idxP = 1 ; idxP <= DevP ; ++idxP){ for(int idxStep = 0 ; idxStep <= nbStep ; ++idxStep){ - ParticleClass centeredParticle; - centeredParticle.setPosition(0.0,0.0,0.5); - centeredParticle.setPhysicalValue(physicalValue); - centeredParticle.setIndex(0); + Particle centeredParticle; + centeredParticle.position.setPosition(0.0,0.0,0.5); + centeredParticle.physicalValue = physicalValue; - ParticleClass otherParticle; - otherParticle.setPosition(0.0,0.0,startPosition + (idxStep*stepValue)); - otherParticle.setPhysicalValue(physicalValue); - otherParticle.setIndex(1); + Particle otherParticle; + otherParticle.position.setPosition(0.0,0.0,startPosition + (idxStep*stepValue)); + otherParticle.physicalValue = physicalValue; CellClass::Init(idxP); OctreeClass tree(NbLevels, 2, boxWidth, boxCenter); - tree.insert(centeredParticle); - tree.insert(otherParticle); + tree.insert(centeredParticle.position, 0, centeredParticle.physicalValue); + tree.insert(otherParticle.position, 1, otherParticle.physicalValue); KernelClass kernels(idxP, NbLevels, boxWidth, boxCenter); FmmClass algo(&tree,&kernels); algo.execute(); - kernels.directInteractionMutual(¢eredParticle, &otherParticle); + FP2P::MutualParticles(centeredParticle.position.getX(), centeredParticle.position.getY(), + centeredParticle.position.getZ(),centeredParticle.physicalValue, + ¢eredParticle.forces[0],¢eredParticle.forces[1], + ¢eredParticle.forces[2],¢eredParticle.potential, + otherParticle.position.getX(), otherParticle.position.getY(), + otherParticle.position.getZ(),otherParticle.physicalValue, + &otherParticle.forces[0],&otherParticle.forces[1], + &otherParticle.forces[2],&otherParticle.potential); { // Check that each particle has been summed with all other - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - - do{ - ContainerClass::BasicIterator leafIter(*octreeIterator.getCurrentListTargets()); - - while( leafIter.hasNotFinished() ){ - const ParticleClass& other = (leafIter.data().getIndex()==0?centeredParticle:otherParticle); - potentialDiff[idxP].add(other.getPotential(),leafIter.data().getPotential()); + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + const FVector<int>& indexes = leaf->getTargets()->getIndexes(); - leafIter.gotoNext(); + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + const int indexPartOrig = indexes[idxPart]; + const Particle& other = (indexPartOrig==0?centeredParticle:otherParticle); + potentialDiff[idxP].add(other.potential,potentials[idxPart]); } - } while(octreeIterator.moveRight()); + }); } // Print for information - printf("For P %d, particle pos %lf\n", idxP, otherParticle.getPosition().getZ()); + printf("For P %d, particle pos %lf\n", idxP, otherParticle.position.getZ()); printf("Potential diff is = %e \t %e\n", potentialDiff[idxP].getL2Norm(), potentialDiff[idxP].getInfNorm()); diff --git a/Tests/Kernels/testSphericalBlasAlgorithm.cpp b/Tests/Kernels/testSphericalBlasAlgorithm.cpp index 9fca7cfc1..5d3ac19eb 100755 --- a/Tests/Kernels/testSphericalBlasAlgorithm.cpp +++ b/Tests/Kernels/testSphericalBlasAlgorithm.cpp @@ -38,9 +38,9 @@ #include "../../Src/Kernels/Spherical/FSphericalKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalBlasKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" #include "../../Src/Files/FFmaScanfLoader.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" /** This program show an example of use of * the fmm blas algo @@ -51,17 +51,16 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FSphericalParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainer ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FSphericalBlasKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSphericalBlasKernel< CellClass, ContainerClass > KernelClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - typedef FFmmAlgorithmThread<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassThread; - typedef FFmmAlgorithmTask<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassTask; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassThread; + typedef FFmmAlgorithmTask<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassTask; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test Spherical Blas algorithm.\n"; std::cout << ">> You can pass -sequential or -task (thread by default).\n"; @@ -74,7 +73,7 @@ int main(int argc, char ** argv){ const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; - FFmaScanfLoader<ParticleClass> loader(filename); + FFmaScanfLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << " is missing\n"; return 1; @@ -90,7 +89,12 @@ int main(int argc, char ** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - loader.fillTree(tree); + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint particlePosition; + FReal physicalValue = 0.0; + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition, physicalValue ); + } counter.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; @@ -130,20 +134,25 @@ int main(int argc, char ** argv){ { // get sum forces&potential FReal potential = 0; - FPoint forces; - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - do{ - ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets()); - while( iter.hasNotFinished() ){ - potential += iter.data().getPotential() * iter.data().getPhysicalValue(); - forces += iter.data().getForces(); - - iter.gotoNext(); + FReal fx = 0.0, fy = 0.0, fz = 0.0; + + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues(); + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + potential += potentials[idxPart] * physicalValues[idxPart]; + fx += forcesX[idxPart]; + fy += forcesY[idxPart]; + fz += forcesZ[idxPart]; } - } while(octreeIterator.moveRight()); + }); - std::cout << "Foces Sum x = " << forces.getX() << " y = " << forces.getY() << " z = " << forces.getZ() << std::endl; + std::cout << "Foces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; std::cout << "Potential = " << potential << std::endl; } diff --git a/Tests/Kernels/testSphericalBlockBlasAlgorithm.cpp b/Tests/Kernels/testSphericalBlockBlasAlgorithm.cpp index c3d0f4922..3f35e8785 100755 --- a/Tests/Kernels/testSphericalBlockBlasAlgorithm.cpp +++ b/Tests/Kernels/testSphericalBlockBlasAlgorithm.cpp @@ -37,11 +37,12 @@ #include "../../Src/Components/FBasicCell.hpp" #include "../../Src/Kernels/Spherical/FSphericalBlockBlasKernel.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" #include "../../Src/Files/FFmaScanfLoader.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that eachh particles is little or longer @@ -52,17 +53,16 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FSphericalParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainer ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FSphericalBlockBlasKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSphericalBlockBlasKernel< CellClass, ContainerClass > KernelClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - typedef FFmmAlgorithmThread<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassThread; - typedef FFmmAlgorithmTask<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassTask; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassThread; + typedef FFmmAlgorithmTask<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassTask; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test Spherical Block Blas algorithm.\n"; std::cout << ">> You can pass -sequential or -task (thread by default).\n"; @@ -75,7 +75,7 @@ int main(int argc, char ** argv){ const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; - FFmaScanfLoader<ParticleClass> loader(filename); + FFmaScanfLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << " is missing\n"; return 1; @@ -91,7 +91,12 @@ int main(int argc, char ** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - loader.fillTree(tree); + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint particlePosition; + FReal physicalValue = 0.0; + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition, physicalValue ); + } counter.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; @@ -131,20 +136,25 @@ int main(int argc, char ** argv){ { // get sum forces&potential FReal potential = 0; - FPoint forces; - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - do{ - ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets()); - while( iter.hasNotFinished() ){ - potential += iter.data().getPotential() * iter.data().getPhysicalValue(); - forces += iter.data().getForces(); - - iter.gotoNext(); + FReal fx = 0.0, fy = 0.0, fz = 0.0; + + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues(); + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + potential += potentials[idxPart] * physicalValues[idxPart]; + fx += forcesX[idxPart]; + fy += forcesY[idxPart]; + fz += forcesZ[idxPart]; } - } while(octreeIterator.moveRight()); + }); - std::cout << "Foces Sum x = " << forces.getX() << " y = " << forces.getY() << " z = " << forces.getZ() << std::endl; + std::cout << "Foces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; std::cout << "Potential = " << potential << std::endl; } diff --git a/Tests/Kernels/testSphericalEwalAlgorithm.cpp b/Tests/Kernels/testSphericalEwalAlgorithm.cpp index be3705d1f..8e13fcc42 100755 --- a/Tests/Kernels/testSphericalEwalAlgorithm.cpp +++ b/Tests/Kernels/testSphericalEwalAlgorithm.cpp @@ -31,29 +31,35 @@ #include "../../Src/Kernels/Spherical/FSphericalKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" #include "../../Src/Files/FEwalLoader.hpp" #include "../../Src/Components/FSimpleLeaf.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp" + /** Ewal particle is used in the gadget program * here we try to make the same simulation */ - +struct EwalParticle { + FPoint position; + FReal forces[3]; + FReal physicalValue; + FReal potential; + int index; +}; // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FEwalParticle<FSphericalParticle> ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainerIndexed ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FSphericalKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSphericalKernel< CellClass, ContainerClass > KernelClass; - typedef FFmmAlgorithmPeriodic<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassNoPer; + typedef FFmmAlgorithmPeriodic<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassNoPer; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test Spherical algorithm.\n"; @@ -75,8 +81,8 @@ int main(int argc, char ** argv){ // ----------------------------------------------------- std::cout << "Opening : " << filename << "\n"; - //FEwalLoader<ParticleClass> loader(filename); - FEwalBinLoader<ParticleClass> loader(filename); + //FEwalLoader loader(filename); + FEwalBinLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << " is missing\n"; return 1; @@ -96,16 +102,14 @@ int main(int argc, char ** argv){ counter.tic(); - ParticleClass * const particles = new ParticleClass[loader.getNumberOfParticles()]; + EwalParticle * const particles = new EwalParticle[loader.getNumberOfParticles()]; + memset(particles, 0, sizeof(EwalParticle) * loader.getNumberOfParticles()); for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - loader.fillParticle(particles[idxPart]); + loader.fillParticle(&particles[idxPart].position, particles[idxPart].forces, + &particles[idxPart].physicalValue,&particles[idxPart].index); // reset forces and insert in the tree - particles[idxPart].setIndex(idxPart); - ParticleClass part = particles[idxPart]; - part.setForces(0,0,0); - part.setPotential(0); - tree.insert(part); + tree.insert(particles[idxPart].position, idxPart, particles[idxPart].physicalValue); } counter.tac(); @@ -138,28 +142,33 @@ int main(int argc, char ** argv){ // ----------------------------------------------------- - ParticleClass* particlesDirect = 0; + EwalParticle* particlesDirect = 0; // Do direct if(FParameters::existParameter(argc, argv, "-direct")){ printf("Compute direct:\n"); printf("Box [%d;%d][%d;%d][%d;%d]\n", min.getX(), max.getX(), min.getY(), max.getY(), min.getZ(), max.getZ()); - KernelClass kernels( DevP, NbLevels, loader.getBoxWidth(), loader.getCenterOfBox()); - particlesDirect = new ParticleClass[loader.getNumberOfParticles()]; + particlesDirect = new EwalParticle[loader.getNumberOfParticles()]; FReal dpotential = 0.0; FMath::FAccurater dfx, dfy, dfz; for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){ - ParticleClass part = particles[idxTarget]; - part.setForces(0,0,0); - part.setPotential(0); + EwalParticle part = particles[idxTarget]; + part.forces[0] = part.forces[1] = part.forces[2] = 0.0; + part.potential = 0.0; // compute with all other except itself for(int idxOther = 0; idxOther < loader.getNumberOfParticles() ; ++idxOther){ if( idxOther != idxTarget ){ - kernels.directInteraction(&part, particles[idxOther]); + FP2P::NonMutualParticles( + particles[idxOther].position.getX(), particles[idxOther].position.getY(), + particles[idxOther].position.getZ(),particles[idxOther].physicalValue, + part.position.getX(), part.position.getY(), + part.position.getZ(),part.physicalValue, + &part.forces[0],&part.forces[1], + &part.forces[2],&part.potential); } } for(int idxX = min.getX() ; idxX <= max.getX() ; ++idxX){ @@ -172,20 +181,26 @@ int main(int argc, char ** argv){ loader.getBoxWidth() * FReal(idxZ)); for(int idxSource = 0 ; idxSource < loader.getNumberOfParticles() ; ++idxSource){ - ParticleClass source = particles[idxSource]; - source.incPosition(offset.getX(),offset.getY(),offset.getZ()); - kernels.directInteraction(&part, source); + EwalParticle source = particles[idxSource]; + source.position += offset; + FP2P::NonMutualParticles( + source.position.getX(), source.position.getY(), + source.position.getZ(),source.physicalValue, + part.position.getX(), part.position.getY(), + part.position.getZ(),part.physicalValue, + &part.forces[0],&part.forces[1], + &part.forces[2],&part.potential + ); } } } } + dfx.add(particles[idxTarget].forces[0],-part.forces[0]*coeff_MD1); + dfy.add(particles[idxTarget].forces[1],-part.forces[1]*coeff_MD1); + dfz.add(particles[idxTarget].forces[2],-part.forces[2]*coeff_MD1); - dfx.add(particles[idxTarget].getForces().getX(),-part.getForces().getX()*coeff_MD1); - dfy.add(particles[idxTarget].getForces().getY(),-part.getForces().getY()*coeff_MD1); - dfz.add(particles[idxTarget].getForces().getZ(),-part.getForces().getZ()*coeff_MD1); - - dpotential += part.getPotential() * part.getPhysicalValue(); + dpotential += part.potential * part.physicalValue; particlesDirect[idxTarget] = part; } @@ -209,49 +224,39 @@ int main(int argc, char ** argv){ FMath::FAccurater potentialDiff; FMath::FAccurater fx, fy, fz; - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - do{ - ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets()); - while( iter.hasNotFinished() ){ - const ParticleClass& part = particles[iter.data().getIndex()]; - - // Check values ------------------------------------------------------------ - potential += iter.data().getPotential() * iter.data().getPhysicalValue(); - - potentialDiff.add(part.getPotential(),-iter.data().getPotential()); - fx.add(part.getForces().getX(),-iter.data().getForces().getX()*coeff_MD1); - fy.add(part.getForces().getY(),-iter.data().getForces().getY()*coeff_MD1); - fz.add(part.getForces().getZ(),-iter.data().getForces().getZ()*coeff_MD1); + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const FReal*const physicalValues = leaf->getTargets()->getPhysicalValues(); + const FReal*const positionsX = leaf->getTargets()->getPositions()[0]; + const FReal*const positionsY = leaf->getTargets()->getPositions()[1]; + const FReal*const positionsZ = leaf->getTargets()->getPositions()[2]; + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + const FVector<int>& indexes = leaf->getTargets()->getIndexes(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + const int indexPartOrig = indexes[idxPart]; + potentialDiff.add(particles[indexPartOrig].potential,potentials[idxPart]); + fx.add(particles[indexPartOrig].forces[0],forcesX[idxPart]); + fy.add(particles[indexPartOrig].forces[1],forcesY[idxPart]); + fz.add(particles[indexPartOrig].forces[2],forcesZ[idxPart]); if(FParameters::existParameter(argc, argv, "-verbose")){ - std::cout << ">> index " << iter.data().getIndexInFile() << std::endl; - std::cout << "Good x " << part.getPosition().getX() << " y " << part.getPosition().getY() << " z " << part.getPosition().getZ() << std::endl; - std::cout << "FMM x " << iter.data().getPosition().getX() << " y " << iter.data().getPosition().getY() << " z " << iter.data().getPosition().getZ() << std::endl; - std::cout << "Good fx " <<part.getForces().getX() << " fy " << part.getForces().getY() << " fz " << part.getForces().getZ() << std::endl; - std::cout << "FMM fx " << iter.data().getForces().getX()*coeff_MD1 << " fy " << iter.data().getForces().getY()*coeff_MD1 << " fz " << iter.data().getForces().getZ()*coeff_MD1 << std::endl; - std::cout << "GOOD physical value " << part.getPhysicalValue() << " potential " << part.getPotential() << std::endl; - std::cout << "FMM physical value " << iter.data().getPhysicalValue() << " potential " << iter.data().getPotential() << std::endl; - - // print result - if(FParameters::existParameter(argc, argv, "-verbose") - && FParameters::existParameter(argc, argv, "-direct")){ - const int idxTarget = iter.data().getIndex(); - std::cout << ">> index in array " << idxTarget << std::endl; - std::cout << "Direct x " << particlesDirect[idxTarget].getPosition().getX() << " y " << particlesDirect[idxTarget].getPosition().getY() << " z " << particles[idxTarget].getPosition().getZ() << std::endl; - std::cout << "Direct fx " << particlesDirect[idxTarget].getForces().getX()*coeff_MD1 << " fy " << particlesDirect[idxTarget].getForces().getY()*coeff_MD1 << " fz " << particlesDirect[idxTarget].getForces().getZ()*coeff_MD1 << std::endl; - std::cout << "Direct physical value " << particlesDirect[idxTarget].getPhysicalValue() << " potential " << particlesDirect[idxTarget].getPotential() << std::endl; - } + std::cout << ">> index " << particles[indexPartOrig].index << std::endl; + std::cout << "Good x " << particles[indexPartOrig].position.getX() << " y " << particles[indexPartOrig].position.getY() << " z " << particles[indexPartOrig].position.getZ() << std::endl; + std::cout << "FMM x " << positionsX[idxPart] << " y " << positionsY[idxPart] << " z " << positionsZ[idxPart] << std::endl; + std::cout << "Good fx " <<particles[indexPartOrig].forces[0] << " fy " << particles[indexPartOrig].forces[1] << " fz " << particles[indexPartOrig].forces[2] << std::endl; + std::cout << "FMM fx " << forcesX[idxPart]*coeff_MD1 << " fy " << forcesY[idxPart]*coeff_MD1 << " fz " << forcesZ[idxPart]*coeff_MD1 << std::endl; + std::cout << "GOOD physical value " << particles[indexPartOrig].physicalValue << " potential " << particles[indexPartOrig].potential << std::endl; + std::cout << "FMM physical value " << physicalValues[idxPart] << " potential " << potentials[idxPart] << std::endl; std::cout << "\n"; } - - // Progress ------------------------------------------------------------------ - - iter.gotoNext(); } - } while(octreeIterator.moveRight()); + }); printf("Difference between FMM and poly:\n"); printf("Potential diff is = \n"); @@ -274,30 +279,24 @@ int main(int argc, char ** argv){ { // get sum forces&potential FReal potential = 0; - FPoint forces; - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - do{ - ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets()); - while( iter.hasNotFinished() ){ - potential += iter.data().getPotential() * iter.data().getPhysicalValue(); - forces += iter.data().getForces(); - - if(FParameters::existParameter(argc, argv, "-verbose")){ - std::cout << " " << iter.data().getIndex()+1 << " \t "<< iter.data().getType() << " \t " << - std::setprecision(5)<< iter.data().getPosition().getX() << " \t" << - iter.data().getPosition().getY() << " \t" << - iter.data().getPosition().getZ() << " Forces: \t"<< - std::setprecision(8) << iter.data().getForces().getX()*coeff_MD1 << " \t " << - iter.data().getForces().getY()*coeff_MD1 << " \t " << - iter.data().getForces().getZ()*coeff_MD1 << std::endl; - } - - iter.gotoNext(); + FReal fx = 0.0, fy = 0.0, fz = 0.0; + + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + potential += potentials[idxPart]; + fx += forcesX[idxPart]; + fy += forcesY[idxPart]; + fz += forcesZ[idxPart]; } - } while(octreeIterator.moveRight()); + }); - std::cout << "Foces Sum x = " << forces.getX() << " y = " << forces.getY() << " z = " << forces.getZ() << std::endl; + std::cout << "Foces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; std::cout << "Potential = " << std::setprecision(8) << potential*coeff_MD/2 << std::endl; std::cout << "Energy from file = " << std::setprecision(8) << loader.getEnergy() << std::endl; // std::cout << "Constante DL_POLY: " << coeff_MD << std::endl; diff --git a/Tests/Kernels/testSphericalGalaxyCsv.cpp b/Tests/Kernels/testSphericalGalaxyCsv.cpp index 00560b72b..4a71f2a14 100755 --- a/Tests/Kernels/testSphericalGalaxyCsv.cpp +++ b/Tests/Kernels/testSphericalGalaxyCsv.cpp @@ -30,9 +30,6 @@ #include "../../Src/Kernels/Spherical/FSphericalKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" - -#include "../../Src/Extensions/FExtendVelocity.hpp" #include "../../Src/Files/FTreeCsvSaver.hpp" #include "../../Src/Files/FFmaLoader.hpp" @@ -40,48 +37,109 @@ #include "../../Src/Components/FSimpleLeaf.hpp" -class FmmVeloParticle : public FSphericalParticle, public FExtendVelocity { +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" + + +class VelocityContainer : public FP2PParticleContainer { + typedef FP2PParticleContainer Parent; + + FVector<FPoint> velocities; + +public: + template<typename... Args> + void push(const FPoint& inParticlePosition, const FPoint& velocity, Args... args){ + Parent::push(inParticlePosition, args... ); + velocities.push(velocity); + } + + const FVector<FPoint>& getVelocities() const{ + return velocities; + } + + FVector<FPoint>& getVelocities() { + return velocities; + } + + void fillToCsv(const int partIdx, FReal values[4]) const { + values[0] = Parent::getPositions()[0][partIdx]; + values[1] = Parent::getPositions()[1][partIdx]; + values[2] = Parent::getPositions()[2][partIdx]; + values[3] = Parent::getPotentials()[partIdx]; + } }; -template <class ParticleClass> -class GalaxyLoader : public FFmaLoader<ParticleClass> { + +class GalaxyLoader : public FFmaLoader { public: - GalaxyLoader(const char* const filename) : FFmaLoader<ParticleClass>(filename) { + GalaxyLoader(const char* const filename) : FFmaLoader(filename) { } - void fillParticle(ParticleClass& inParticle){ + void fillParticle(FPoint* position, FReal* physivalValue, FPoint* velocity){ FReal x,y,z,data, vx, vy, vz; this->file >> x >> y >> z >> data >> vx >> vy >> vz; - inParticle.setPosition(x,y,z); - inParticle.setPhysicalValue(data); - inParticle.setVelocity(vx,vy,vz); + position->setPosition(x,y,z); + *physivalValue = (data); + velocity->setPosition(vx,vy,vz); } }; +template <class ContainerClass> +class GalaxyExtractor { + struct Particle{ + FPoint position; + FReal physicalValue; + FReal forces[3]; + FReal potential; + FPoint velocity; + }; + + FVector<Particle> savedParticles; -template <class OctreeClass, class ContainerClass , class ParticleClass> -class MassSaver : public FTreeCsvSaver<OctreeClass,ContainerClass, ParticleClass> { public: - MassSaver(const char inBasefile[], const bool inIncludeHeader = false) - : FTreeCsvSaver<OctreeClass,ContainerClass, ParticleClass> (inBasefile,inIncludeHeader) { + void extractParticles(const ContainerClass* containers, const int indexesToExtract[], const int nbToExtract){ + const FReal*const positionsX = containers->getPositions()[0]; + const FReal*const positionsY = containers->getPositions()[1]; + const FReal*const positionsZ = containers->getPositions()[2]; + const FReal*const forcesX = containers->getForcesX(); + const FReal*const forcesY = containers->getForcesY(); + const FReal*const forcesZ = containers->getForcesZ(); + const FReal*const physicalValues = containers->getPhysicalValues(); + const FReal*const potentials = containers->getPotentials(); + FVector<FPoint> velocites = containers->getVelocities(); + + for(int idxPart = 0 ; idxPart < nbToExtract ; ++ idxPart){ + const int idxExtract = indexesToExtract[idxPart]; + Particle part; + part.position.setPosition( positionsX[idxExtract],positionsY[idxExtract],positionsZ[idxExtract]); + part.physicalValue = physicalValues[idxExtract]; + part.forces[0] = forcesX[idxExtract]; + part.forces[1] = forcesY[idxExtract]; + part.forces[2] = forcesZ[idxExtract]; + part.potential = potentials[idxExtract]; + part.velocity = velocites[idxExtract]; + } } - virtual FReal getValue(ParticleClass*const part){ - return part->getPhysicalValue(); + template <class OctreeClass> + void reinsertInTree(OctreeClass* tree){ + for(int idxPart = 0 ; idxPart < savedParticles.getSize() ; ++idxPart){ + const Particle part = savedParticles[idxPart]; + tree->insert(part.position, part.velocity, part.physicalValue, part.forces[0], + part.forces[1],part.forces[2],part.potential); + } } }; // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FmmVeloParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef VelocityContainer ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FSphericalKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSphericalKernel< CellClass, ContainerClass > KernelClass; - typedef FFmmAlgorithmThread<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test Spherical algorithm.\n"; ////////////////////////////////////////////////////////////// @@ -93,7 +151,7 @@ int main(int argc, char ** argv){ FSphericalCell::Init(DevP); - GalaxyLoader<ParticleClass> loader(FParameters::getStr(argc,argv,"-f", "../Data/galaxy.fma.tmp")); + GalaxyLoader loader(FParameters::getStr(argc,argv,"-f", "../Data/galaxy.fma.tmp")); // ----------------------------------------------------- @@ -105,12 +163,12 @@ int main(int argc, char ** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; { - ParticleClass particleToFill; - particleToFill.setPhysicalValue(FReal(0.10)); + FPoint position, velocity; + FReal physicalValue; for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - loader.fillParticle(particleToFill); - tree.insert(particleToFill); + loader.fillParticle(&position, &physicalValue, &velocity); + tree.insert(position, velocity, physicalValue); } } @@ -118,8 +176,8 @@ int main(int argc, char ** argv){ KernelClass kernels( DevP, NbLevels, loader.getBoxWidth(), loader.getCenterOfBox()); FmmClass algo( &tree, &kernels); - FOctreeArranger<OctreeClass, ContainerClass, ParticleClass> arranger(&tree); - MassSaver<OctreeClass, ContainerClass, ParticleClass> saver("./out/test%d.csv"); + FOctreeArranger<OctreeClass, ContainerClass, GalaxyExtractor<ContainerClass> > arranger(&tree); + FTreeCsvSaver<OctreeClass, ContainerClass> saver("./out/test%d.csv"); for(int idx = 0; idx < 100 ; ++idx){ algo.execute(); @@ -127,12 +185,8 @@ int main(int argc, char ** argv){ OctreeClass::Iterator octreeIterator(&tree); octreeIterator.gotoBottomLeft(); do{ - ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListTargets()); - while( iter.hasNotFinished() ){ - kernels.computeVelocity(&iter.data(), DT); - kernels.updatePosition(&iter.data(), DT); - iter.gotoNext(); - } + kernels.computeVelocity(octreeIterator.getCurrentListTargets(), DT); + kernels.updatePosition(octreeIterator.getCurrentListTargets(), DT); } while(octreeIterator.moveRight()); } // update tree and vtk diff --git a/Tests/Kernels/testSphericalRotationAlgorithm.cpp b/Tests/Kernels/testSphericalRotationAlgorithm.cpp index d83561db9..11c628020 100755 --- a/Tests/Kernels/testSphericalRotationAlgorithm.cpp +++ b/Tests/Kernels/testSphericalRotationAlgorithm.cpp @@ -33,10 +33,11 @@ #include "../../Src/Kernels/Spherical/FSphericalRotationKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" #include "../../Src/Files/FFmaScanfLoader.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that eachh particles is little or longer @@ -46,17 +47,16 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FSphericalParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainer ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FSphericalRotationKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSphericalRotationKernel< CellClass, ContainerClass > KernelClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - typedef FFmmAlgorithmThread<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassThread; - typedef FFmmAlgorithmTask<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassTask; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassThread; + typedef FFmmAlgorithmTask<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassTask; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test Spherical Rotation algorithm.\n"; std::cout << ">> You can pass -sequential or -task (thread by default).\n"; @@ -69,7 +69,7 @@ int main(int argc, char ** argv){ const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; - FFmaScanfLoader<ParticleClass> loader(filename); + FFmaScanfLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << " is missing\n"; return 1; @@ -85,7 +85,12 @@ int main(int argc, char ** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - loader.fillTree(tree); + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint particlePosition; + FReal physicalValue = 0.0; + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition, physicalValue ); + } counter.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; @@ -125,20 +130,24 @@ int main(int argc, char ** argv){ { // get sum forces&potential FReal potential = 0; - FPoint forces; - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - do{ - ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets()); - while( iter.hasNotFinished() ){ - potential += iter.data().getPotential() * iter.data().getPhysicalValue(); - forces += iter.data().getForces(); - - iter.gotoNext(); + FReal fx = 0.0, fy = 0.0, fz = 0.0; + + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + potential += potentials[idxPart]; + fx += forcesX[idxPart]; + fy += forcesY[idxPart]; + fz += forcesZ[idxPart]; } - } while(octreeIterator.moveRight()); + }); - std::cout << "Foces Sum x = " << forces.getX() << " y = " << forces.getY() << " z = " << forces.getZ() << std::endl; + std::cout << "Foces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; std::cout << "Potential = " << potential << std::endl; } diff --git a/Tests/Kernels/testSphericalTsmAlgorithm.cpp b/Tests/Kernels/testSphericalTsmAlgorithm.cpp index 9a9d71c8a..f953cb7dc 100755 --- a/Tests/Kernels/testSphericalTsmAlgorithm.cpp +++ b/Tests/Kernels/testSphericalTsmAlgorithm.cpp @@ -31,10 +31,11 @@ #include "../../Src/Kernels/Spherical/FSphericalKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" #include "../../Src/Files/FFmaTsmLoader.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that eachh particles is little or longer @@ -44,15 +45,14 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FTypedSphericalParticle ParticleClass; typedef FTypedSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainer ContainerClass; - typedef FTypedLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FSphericalKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FTypedLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSphericalKernel< CellClass, ContainerClass > KernelClass; - typedef FFmmAlgorithmTsm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithmTsm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test Spherical on a Tsm system.\n"; ////////////////////////////////////////////////////////////// @@ -64,7 +64,7 @@ int main(int argc, char ** argv){ const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.tsm.fma"); std::cout << "Opening : " << filename << "\n"; - FFmaTsmLoader<ParticleClass> loader(filename); + FFmaTsmLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << " is missing\n"; return 1; @@ -80,7 +80,13 @@ int main(int argc, char ** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - loader.fillTree(tree); + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint particlePosition; + FReal physicalValue = 0.0; + bool isTarget; + loader.fillParticle(&particlePosition,&physicalValue,&isTarget); + tree.insert(particlePosition, isTarget, physicalValue ); + } counter.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; @@ -109,20 +115,24 @@ int main(int argc, char ** argv){ { // get sum forces&potential FReal potential = 0; - FPoint forces; - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - do{ - FVector<ParticleClass>::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets()); - while( iter.hasNotFinished() ){ - potential += iter.data().getPotential() * iter.data().getPhysicalValue(); - forces += iter.data().getForces(); - - iter.gotoNext(); + FReal fx = 0.0, fy = 0.0, fz = 0.0; + + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + potential += potentials[idxPart]; + fx += forcesX[idxPart]; + fy += forcesY[idxPart]; + fz += forcesZ[idxPart]; } - } while(octreeIterator.moveRight()); + }); - std::cout << "Foces Sum x = " << forces.getX() << " y = " << forces.getY() << " z = " << forces.getZ() << std::endl; + std::cout << "Foces Sum x = " << fx << " y = " << fy << " z = " << fz << std::endl; std::cout << "Potential = " << potential << std::endl; } diff --git a/Tests/Kernels/testSphericalTsmNoTsm.cpp b/Tests/Kernels/testSphericalTsmNoTsm.cpp deleted file mode 100755 index fc4dd6e0a..000000000 --- a/Tests/Kernels/testSphericalTsmNoTsm.cpp +++ /dev/null @@ -1,200 +0,0 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== - -#include <iostream> - -#include <cstdio> -#include <cstdlib> - -#include "../../Src/Utils/FTic.hpp" -#include "../../Src/Utils/FParameters.hpp" - -#include "../../Src/Containers/FOctree.hpp" -#include "../../Src/Containers/FVector.hpp" - -#include "../../Src/Kernels/Spherical/FSphericalKernel.hpp" -#include "../../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" - -#include "../../Src/Core/FFmmAlgorithm.hpp" -#include "../../Src/Core/FFmmAlgorithmTsm.hpp" -#include "../../Src/Core/FFmmAlgorithmThread.hpp" -#include "../../Src/Core/FFmmAlgorithmThreadTsm.hpp" - -#include "../../Src/Components/FSimpleLeaf.hpp" -#include "../../Src/Components/FTypedLeaf.hpp" - - -/** This program show an example of use of - * the fmm basic algo - * it also check that eachh particles is little or longer - * related that each other - */ - - -// Simply create particles and try the kernels -int main(int argc, char ** argv){ - typedef FSphericalParticle ParticleClass; - typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; - - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FSphericalKernel<ParticleClass, CellClass, ContainerClass > KernelClass; - - typedef FFmmAlgorithmThread<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - - typedef FTypedSphericalParticle ParticleClassTyped; - typedef FTypedSphericalCell CellClassTyped; - typedef FVector<ParticleClassTyped> ContainerClassTyped; - - typedef FTypedLeaf<ParticleClassTyped, ContainerClassTyped > LeafClassTyped; - typedef FOctree<ParticleClassTyped, CellClassTyped, ContainerClassTyped , LeafClassTyped > OctreeClassTyped; - typedef FSphericalKernel<ParticleClassTyped, CellClassTyped, ContainerClassTyped > KernelClassTyped; - - typedef FFmmAlgorithmThreadTsm<OctreeClassTyped, ParticleClassTyped, CellClassTyped, ContainerClassTyped, KernelClassTyped, LeafClassTyped > FmmClassTyped; - - ///////////////////////What we do///////////////////////////// - std::cout << ">> This executable has to be used to test Spherical on a Tsm system.\n"; - std::cout << ">> It compares the results between Tms and no Tms (except P2P & L2P).\n"; - ////////////////////////////////////////////////////////////// - const int DevP = FParameters::getValue(argc,argv,"-p", 8); - const int NbLevels = FParameters::getValue(argc,argv,"-h", 5); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); - FTic counter; - const int NbPart = 200000;//2000000 - const double BoxWidth = 1.0; - const FPoint CenterOfBox(0.5,0.5,0.5); - const FReal FRandMax = FReal(RAND_MAX); - - - // ----------------------------------------------------- - CellClass::Init(DevP); - - OctreeClass tree(NbLevels, SizeSubLevels,BoxWidth,CenterOfBox); - OctreeClassTyped treeTyped(NbLevels, SizeSubLevels,BoxWidth,CenterOfBox); - - - std::cout << "Inserting particles ..." << std::endl; - counter.tic(); - for(long idxPart = 0 ; idxPart < NbPart ; ++idxPart){ - const FReal x = FReal(rand())/FRandMax; - const FReal y = FReal(rand())/FRandMax; - const FReal z = FReal(rand())/FRandMax; - - ParticleClass particles; - ParticleClassTyped particlesTyped; - ParticleClassTyped particlesTyped2; - - // Particle for standart model - particles.setPosition(x,y,z); - particles.setPhysicalValue(1); - - // Create a clone for typed (Tsm) version - particlesTyped.setPosition(x,y,z); - particlesTyped2.setPosition(x,y,z); - - particlesTyped.setPhysicalValue(1); - particlesTyped2.setPhysicalValue(1); - - particlesTyped.setAsSource(); - particlesTyped2.setAsTarget(); - - tree.insert(particles); - treeTyped.insert(particlesTyped); - treeTyped.insert(particlesTyped2); - } - counter.tac(); - std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; - - // ----------------------------------------------------- - std::cout << "Create kernels ..." << std::endl; - - KernelClass kernels(DevP, NbLevels, BoxWidth, CenterOfBox); - KernelClassTyped kernelsTyped(DevP, NbLevels, BoxWidth, CenterOfBox); - - - std::cout << "Working on particles ..." << std::endl; - - FmmClass algo(&tree,&kernels); - FmmClassTyped algoTyped(&treeTyped,&kernelsTyped); - - counter.tic(); - algo.execute(); - algoTyped.execute(); - - counter.tac(); - std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl; - - // ----------------------------------------------------- - - // Here we compare the cells of the trees that must contains the same values - - std::cout << "Start checking ..." << std::endl; - { - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - - OctreeClassTyped::Iterator octreeIteratorTyped(&treeTyped); - octreeIteratorTyped.gotoBottomLeft(); - - for(int idxLevel = NbLevels - 1 ; idxLevel > 1 ; --idxLevel ){ - std::cout << "\t test level " << idxLevel << "\n"; - - do{ - bool poleDiff = false; - bool localDiff = false; - for(int idxValues = 0 ; idxValues < FSphericalCell::GetPoleSize() && !(poleDiff && localDiff); ++idxValues){ - const FComplexe pole = octreeIterator.getCurrentCell()->getMultipole()[idxValues]; - const FComplexe poleTyped = octreeIteratorTyped.getCurrentCell()->getMultipole()[idxValues]; - if(!FMath::LookEqual(pole.getImag(),poleTyped.getImag()) || !FMath::LookEqual(pole.getReal(),poleTyped.getReal())){ - poleDiff = true; - printf("Pole diff imag( %.15e , %.15e ) real( %.15e , %.15e)\n", - pole.getImag(),poleTyped.getImag(),pole.getReal(),poleTyped.getReal()); - } - } - for(int idxValues = 0 ; idxValues < FSphericalCell::GetPoleSize() && !(poleDiff && localDiff); ++idxValues){ - const FComplexe local = octreeIterator.getCurrentCell()->getLocal()[idxValues]; - const FComplexe localTyped = octreeIteratorTyped.getCurrentCell()->getLocal()[idxValues]; - if(!FMath::LookEqual(local.getImag(),localTyped.getImag()) || !FMath::LookEqual(local.getReal(),localTyped.getReal())){ - localDiff = true; - printf("Pole diff imag( %.15e , %.15e ) real( %.15e , %.15e)\n", - local.getImag(),localTyped.getImag(),local.getReal(),localTyped.getReal()); - } - } - if(poleDiff){ - std::cout << "Multipole error at level " << idxLevel << "\n"; - } - if(localDiff){ - std::cout << "Locale error at level " << idxLevel << "\n"; - } - } while(octreeIterator.moveRight() && octreeIteratorTyped.moveRight()); - - octreeIterator.moveUp(); - octreeIterator.gotoLeft(); - - octreeIteratorTyped.moveUp(); - octreeIteratorTyped.gotoLeft(); - } - } - - std::cout << "Done ..." << std::endl; - - return 0; -} - - - diff --git a/Tests/Kernels/testTuneSphericalBlockBlas.cpp b/Tests/Kernels/testTuneSphericalBlockBlas.cpp index bbfe1ad42..11e19c687 100755 --- a/Tests/Kernels/testTuneSphericalBlockBlas.cpp +++ b/Tests/Kernels/testTuneSphericalBlockBlas.cpp @@ -36,11 +36,12 @@ #include "../../Src/Components/FBasicCell.hpp" #include "../../Src/Kernels/Spherical/FSphericalBlockBlasKernel.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" #include "../../Src/Files/FFmaScanfLoader.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" + /** This program find the best block blas size */ @@ -48,15 +49,14 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FSphericalParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainer ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FSphericalBlockBlasKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSphericalBlockBlasKernel< CellClass, ContainerClass > KernelClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test Spherical algorithm.\n"; ////////////////////////////////////////////////////////////// @@ -69,15 +69,13 @@ int main(int argc, char ** argv){ const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; - - // ----------------------------------------------------- double minTime = 999999999999999999.0; int bestSize = -1; CellClass::Init(DevP, true); for(int idxBlockSize = 1 ; idxBlockSize < MaxBlockSize ; idxBlockSize *= 2){ - FFmaScanfLoader<ParticleClass> loader(filename); + FFmaScanfLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << " is missing\n"; return 1; @@ -87,7 +85,12 @@ int main(int argc, char ** argv){ // ----------------------------------------------------- - loader.fillTree(tree); + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint particlePosition; + FReal physicalValue = 0.0; + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition, physicalValue ); + } // ----------------------------------------------------- diff --git a/Tests/Utils/testChebInterpolator.cpp b/Tests/Utils/testChebInterpolator.cpp index 9db12aa4a..3310e8636 100755 --- a/Tests/Utils/testChebInterpolator.cpp +++ b/Tests/Utils/testChebInterpolator.cpp @@ -33,11 +33,12 @@ #include "../../Src/Utils/FAssertable.hpp" #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Kernels/Chebyshev/FChebParticle.hpp" #include "../../Src/Kernels/Chebyshev/FChebLeaf.hpp" #include "../../Src/Kernels/Chebyshev/FChebInterpolator.hpp" #include "../../Src/Kernels/Chebyshev/FChebMatrixKernel.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" +#include "../../Src/Components/FSimpleLeaf.hpp" @@ -73,11 +74,9 @@ FReal computeINFnorm(unsigned int N, FReal *const u, FReal *const v) * In this file we show how to use octree */ -int main(int, char **){ - - typedef FChebParticle ParticleClass; - typedef FVector<FChebParticle> ContainerClass; - typedef FChebLeaf<ParticleClass,ContainerClass> LeafClass; +int main(int, char **){ + typedef FP2PParticleContainer ContainerClass; + typedef FSimpleLeaf<ContainerClass> LeafClass; typedef FChebMatrixKernelR MatrixKernelClass; @@ -101,15 +100,12 @@ int main(int, char **){ const unsigned long M = 20000; std::cout << "Fill the leaf X of width " << width << " centered at cx=" << cx << " with M=" << M << " target particles" << std::endl; - { - FChebParticle particle; + { for(unsigned long i=0; i<M; ++i){ FReal x = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getX(); FReal y = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getY(); FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getZ(); - particle.setPosition(x, y, z); - particle.setPhysicalValue(FReal(rand())/FRandMax); - X.push(particle); + X.push(FPoint(x, y, z), FReal(rand())/FRandMax); } } @@ -120,15 +116,12 @@ int main(int, char **){ const unsigned long N = 20000; std::cout << "Fill the leaf Y of width " << width << " centered at cy=" << cy << " with N=" << N << " target particles" << std::endl; - { - FChebParticle particle; + { for(unsigned long i=0; i<N; ++i){ FReal x = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getX(); FReal y = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getY(); FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getZ(); - particle.setPosition(x, y, z); - particle.setPhysicalValue(FReal(rand())/FRandMax); - Y.push(particle); + Y.push(FPoint(x, y, z), FReal(rand())/FRandMax); } } @@ -194,15 +187,18 @@ int main(int, char **){ { // start direct computation unsigned int counter = 0; - ContainerClass::ConstBasicIterator iterX(*(X.getSrc())); - while(iterX.hasNotFinished()){ - const FPoint& x = iterX.data().getPosition(); - const FReal wx = iterX.data().getPhysicalValue(); + for(int idxPartX = 0 ; idxPartX < X.getSrc()->getNbParticles() ; ++idxPartX){ + const FPoint x = FPoint(X.getSrc()->getPositions()[0][idxPartX], + X.getSrc()->getPositions()[1][idxPartX], + X.getSrc()->getPositions()[2][idxPartX]); + const FReal wx = X.getSrc()->getPhysicalValues()[idxPartX]; - ContainerClass::ConstBasicIterator iterY(*(Y.getSrc())); - while(iterY.hasNotFinished()){ - const FPoint& y = iterY.data().getPosition(); - const FReal wy = iterY.data().getPhysicalValue(); + for(int idxPartY = 0 ; idxPartY < Y.getSrc()->getNbParticles() ; ++idxPartY){ + const FPoint y = FPoint(Y.getSrc()->getPositions()[0][idxPartY], + Y.getSrc()->getPositions()[1][idxPartY], + Y.getSrc()->getPositions()[2][idxPartY]); + const FReal wy = Y.getSrc()->getPhysicalValues()[idxPartY]; + const FReal one_over_r = MatrixKernel.evaluate(x, y); // potential p[counter] += one_over_r * wy; @@ -212,11 +208,9 @@ int main(int, char **){ f[counter*3 + 0] += force.getX() * wx * wy; f[counter*3 + 1] += force.getY() * wx * wy; f[counter*3 + 2] += force.getZ() * wx * wy; - iterY.gotoNext(); } - counter++; - iterX.gotoNext(); + counter++; } } // end direct computation @@ -225,18 +219,18 @@ int main(int, char **){ std::cout << "Done in " << time.elapsed() << "sec." << std::endl; - //////////////////////////////////////////////////////////////////// - ContainerClass::ConstBasicIterator iterX(*(X.getSrc())); + //////////////////////////////////////////////////////////////////// unsigned int counter = 0; - while(iterX.hasNotFinished()) { - approx_p[counter] = iterX.data().getPotential(); - const FPoint& force = iterX.data().getForces(); + for(int idxPartX = 0 ; idxPartX < X.getSrc()->getNbParticles() ; ++idxPartX){ + approx_p[counter] = X.getSrc()->getPotentials()[idxPartX]; + const FPoint force = FPoint(X.getSrc()->getForcesX()[idxPartX], + X.getSrc()->getForcesY()[idxPartX], + X.getSrc()->getForcesZ()[idxPartX]); approx_f[counter*3 + 0] = force.getX(); approx_f[counter*3 + 1] = force.getY(); approx_f[counter*3 + 2] = force.getZ(); - counter++; - iterX.gotoNext(); + counter++; } std::cout << "\nPotential error:" << std::endl; diff --git a/Tests/Utils/testChebOctree.cpp b/Tests/Utils/testChebOctree.cpp index 551288999..54d501e38 100755 --- a/Tests/Utils/testChebOctree.cpp +++ b/Tests/Utils/testChebOctree.cpp @@ -28,10 +28,11 @@ #include "../../Src/Utils/FAssertable.hpp" #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Kernels/Chebyshev/FChebParticle.hpp" #include "../../Src/Kernels/Chebyshev/FChebCell.hpp" #include "../../Src/Kernels/Chebyshev/FChebLeaf.hpp" +#include "../../Src/Components/FSimpleLeaf.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" /** * In this file we show how to use octree @@ -41,11 +42,10 @@ int main(int, char **){ const int ORDER = 5; - typedef FChebParticle ParticleClass; - typedef FVector<FChebParticle> ContainerClass; - typedef FChebLeaf<ParticleClass,ContainerClass> LeafClass; + typedef FP2PParticleContainer ContainerClass; + typedef FSimpleLeaf<ContainerClass> LeafClass; typedef FChebCell<ORDER> CellClass; - typedef FOctree<ParticleClass,CellClass,ContainerClass,LeafClass> OctreeClass; + typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable is useless to execute.\n"; @@ -67,11 +67,9 @@ int main(int, char **){ // ----------------------------------------------------- std::cout << "Creating and inserting " << NbPart << " particles ..." << std::endl; counter.tic(); - { - FChebParticle particle; - for(long idxPart = 0 ; idxPart < NbPart ; ++idxPart){ - particle.setPosition(FReal(rand())/FRandMax,FReal(rand())/FRandMax,FReal(rand())/FRandMax); - tree.insert(particle); + { + for(long idxPart = 0 ; idxPart < NbPart ; ++idxPart){ + tree.insert(FPoint(FReal(rand())/FRandMax,FReal(rand())/FRandMax,FReal(rand())/FRandMax)); } } counter.tac(); @@ -83,30 +81,28 @@ int main(int, char **){ // Check if particles are strictly within its containing leaf cells { const FReal BoxWidthLeaf = BoxWidth / FReal(FMath::pow(2, TreeHeight-1)); - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - do{ - const CellClass *const LeafCell = octreeIterator.getCurrentCell(); - + tree.forEachCellLeaf([&](CellClass* LeafCell, LeafClass* leaf){ const FPoint Origin(BoxCenter - BoxWidth / FReal(2.)); const FPoint LeafCellCenter(Origin.getX() + (FReal(LeafCell->getCoordinate().getX()) + FReal(.5)) * BoxWidthLeaf, Origin.getY() + (FReal(LeafCell->getCoordinate().getY()) + FReal(.5)) * BoxWidthLeaf, Origin.getZ() + (FReal(LeafCell->getCoordinate().getZ()) + FReal(.5)) * BoxWidthLeaf); - const ContainerClass *const Particles = octreeIterator.getCurrentListSrc(); - ContainerClass::ConstBasicIterator particleIterator(*Particles); - while(particleIterator.hasNotFinished()) { - const FPoint distance(LeafCellCenter-particleIterator.data().getPosition()); + const ContainerClass *const Particles = leaf->getSrc(); + const FReal*const positionsX = Particles->getPositions()[0]; + const FReal*const positionsY = Particles->getPositions()[1]; + const FReal*const positionsZ = Particles->getPositions()[2]; + + for(int idxPart = 0 ; idxPart < Particles->getNbParticles() ; ++idxPart){ + const FPoint distance(LeafCellCenter-FPoint(positionsX[idxPart],positionsY[idxPart],positionsZ[idxPart])); if (std::abs(distance.getX())>BoxWidthLeaf/FReal(2.) || std::abs(distance.getY())>BoxWidthLeaf/FReal(2.) || std::abs(distance.getZ())>BoxWidthLeaf/FReal(2.)) { std::cout << "Particle (center - particle = " << distance << " < " << BoxWidthLeaf/FReal(2.) << ") is out of cell. STOP" << std::endl; //exit(-1); - } - particleIterator.gotoNext(); + } } - } while(octreeIterator.moveRight()); + }); } return 0; diff --git a/Tests/Utils/testChebSxUCBSy.cpp b/Tests/Utils/testChebSxUCBSy.cpp index a01cd5521..47174b209 100755 --- a/Tests/Utils/testChebSxUCBSy.cpp +++ b/Tests/Utils/testChebSxUCBSy.cpp @@ -33,11 +33,12 @@ #include "../../Src/Utils/FAssertable.hpp" #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Kernels/Chebyshev/FChebParticle.hpp" #include "../../Src/Kernels/Chebyshev/FChebLeaf.hpp" #include "../../Src/Kernels/Chebyshev/FChebInterpolator.hpp" #include "../../Src/Kernels/Chebyshev/FChebMatrixKernel.hpp" +#include "../../Src/Components/FSimpleLeaf.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" void applyM2M(FReal *const S, FReal *const w, const unsigned int n, FReal *const W, const unsigned int N) { FBlas::gemtva(n, N, FReal(1.), S, w, W); } @@ -76,9 +77,8 @@ FReal computeINFnorm(unsigned int N, FReal *const u, FReal *const v) int main(int argc, char* argv[]) { - typedef FChebParticle ParticleClass; - typedef FVector<FChebParticle> ContainerClass; - typedef FChebLeaf<ParticleClass,ContainerClass> LeafClass; + typedef FP2PParticleContainer ContainerClass; + typedef FSimpleLeaf<ContainerClass> LeafClass; typedef FChebMatrixKernelR MatrixKernelClass; ///////////////////////What we do///////////////////////////// @@ -102,14 +102,12 @@ int main(int argc, char* argv[]) std::cout << "Fill the leaf X of width " << width << " centered at cx=[" << cx.getX() << "," << cx.getY() << "," << cx.getZ() << "] with M=" << M << " target particles" << std::endl; - { - FChebParticle particle; + { for(long i=0; i<M; ++i){ FReal x = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getX(); FReal y = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getY(); - FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getZ(); - particle.setPosition(x, y, z); - X.push(particle); + FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cx.getZ(); + X.push(FPoint(x,y,z)); } } @@ -121,15 +119,12 @@ int main(int argc, char* argv[]) std::cout << "Fill the leaf Y of width " << width << " centered at cy=[" << cy.getX() << "," << cy.getY() << "," << cy.getZ() << "] with N=" << N << " target particles" << std::endl; - { - FChebParticle particle; + { for(long i=0; i<N; ++i){ FReal x = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getX(); FReal y = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getY(); FReal z = (FReal(rand())/FRandMax - FReal(.5)) * width + cy.getZ(); - particle.setPosition(x, y, z); - particle.setPhysicalValue(FReal(rand())/FRandMax); - Y.push(particle); + Y.push(FPoint(x, y, z),FReal(rand())/FRandMax); } } @@ -197,30 +192,36 @@ int main(int argc, char* argv[]) FReal* approx_f = new FReal[M]; FReal* f = new FReal[M]; - for (unsigned int i=0; i<M; ++i) f[i] = FReal(0.); - ContainerClass::ConstBasicIterator iterY(*(Y.getSrc())); - while(iterY.hasNotFinished()){ - const FPoint& y = iterY.data().getPosition(); - const FReal w = iterY.data().getPhysicalValue(); - unsigned int counter = 0; - ContainerClass::ConstBasicIterator iterX(*(X.getSrc())); - while(iterX.hasNotFinished()){ - const FPoint& x = iterX.data().getPosition(); - f[counter++] += MatrixKernel.evaluate(x,y) * w; - iterX.gotoNext(); - } - iterY.gotoNext(); - } + { + for (unsigned int i=0; i<M; ++i) f[i] = FReal(0.); + + const FReal*const positionsX = Y.getSrc()->getPositions()[0]; + const FReal*const positionsY = Y.getSrc()->getPositions()[1]; + const FReal*const positionsZ = Y.getSrc()->getPositions()[2]; + const FReal*const physicalValues = Y.getSrc()->getPhysicalValues(); + + for(int idxPart = 0 ; idxPart < Y.getSrc()->getNbParticles() ; ++idxPart){ + const FPoint y = FPoint(positionsX[idxPart],positionsY[idxPart],positionsZ[idxPart]); + const FReal w = physicalValues[idxPart]; + + const FReal*const xpositionsX = X.getSrc()->getPositions()[0]; + const FReal*const xpositionsY = X.getSrc()->getPositions()[1]; + const FReal*const xpositionsZ = X.getSrc()->getPositions()[2]; + + for(int idxPartX = 0 ; idxPartX < X.getSrc()->getNbParticles() ; ++idxPartX){ + const FPoint x = FPoint(xpositionsX[idxPart],xpositionsY[idxPart],xpositionsZ[idxPart]); + f[idxPartX] += MatrixKernel.evaluate(x,y) * w; + } + } + } time.tac(); std::cout << "Done in " << time.elapsed() << "sec." << std::endl; //////////////////////////////////////////////////////////////////// - ContainerClass::ConstBasicIterator iterX(*(X.getSrc())); - unsigned int counter = 0; - while(iterX.hasNotFinished()) { - approx_f[counter++] = iterX.data().getPotential(); - iterX.gotoNext(); + const FReal*const potentials = X.getSrc()->getPotentials(); + for(int idxPart = 0 ; idxPart < X.getSrc()->getNbParticles() ; ++idxPart){ + approx_f[idxPart] = potentials[idxPart]; } diff --git a/Tests/Utils/testCompareIOTree.cpp b/Tests/Utils/testCompareIOTree.cpp index 324f4aa46..06b385c7f 100755 --- a/Tests/Utils/testCompareIOTree.cpp +++ b/Tests/Utils/testCompareIOTree.cpp @@ -30,19 +30,18 @@ #include "../../Src/Files/FTreeIO.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" #include "../../Src/Components/FSimpleLeaf.hpp" - +#include "../../Src/Components/FSimpleLeaf.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FSphericalParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainer ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to compare two trees.\n"; ////////////////////////////////////////////////////////////// @@ -58,8 +57,8 @@ int main(int argc, char ** argv){ const char* const filename2 = FParameters::getStr(argc,argv,"-f1", "dtree.data"); std::cout << "Compare tree " << filename1 << " and " << filename2 << std::endl; - FTreeIO::Load<OctreeClass, CellClass, ParticleClass, ContainerClass >(filename1, tree1); - FTreeIO::Load<OctreeClass, CellClass, ParticleClass, ContainerClass >(filename2, tree2); + FTreeIO::Load<OctreeClass, CellClass, LeafClass, ContainerClass >(filename1, tree1); + FTreeIO::Load<OctreeClass, CellClass, LeafClass, ContainerClass >(filename2, tree2); // ----------------------------------------------------- std::cout << "Check Result\n"; @@ -78,10 +77,10 @@ int main(int argc, char ** argv){ break; } - if( octreeIterator1.getCurrentListSrc()->getSize() != octreeIterator2.getCurrentListSrc()->getSize()){ + if( octreeIterator1.getCurrentListSrc()->getNbParticles() != octreeIterator2.getCurrentListSrc()->getNbParticles()){ std::cout << "Number of particles different on leaf " << octreeIterator1.getCurrentGlobalIndex() << - " tree1 " << octreeIterator1.getCurrentListSrc()->getSize() << - " tree2 " << octreeIterator2.getCurrentListSrc()->getSize() << std::endl; + " tree1 " << octreeIterator1.getCurrentListSrc()->getNbParticles() << + " tree2 " << octreeIterator2.getCurrentListSrc()->getNbParticles() << std::endl; } nbLeaves += 1; diff --git a/Tests/Utils/testFmmAlgorithm.cpp b/Tests/Utils/testFmmAlgorithm.cpp index e9f2f3cb0..b33692f78 100755 --- a/Tests/Utils/testFmmAlgorithm.cpp +++ b/Tests/Utils/testFmmAlgorithm.cpp @@ -28,7 +28,7 @@ #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Components/FTestParticle.hpp" +#include "../../Src/Components/FTestParticleContainer.hpp" #include "../../Src/Components/FTestCell.hpp" #include "../../Src/Components/FTestKernels.hpp" @@ -47,16 +47,15 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FTestParticle ParticleClass; typedef FTestCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FTestParticleContainer ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FTestKernels<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FTestKernels< CellClass, ContainerClass > KernelClass; // FFmmAlgorithmTask FFmmAlgorithmThread - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test the FMM algorithm.\n"; @@ -70,7 +69,7 @@ int main(int argc, char ** argv){ ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// - FRandomLoader<ParticleClass> loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1); + FRandomLoader loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1); OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); ////////////////////////////////////////////////////////////////////////////////// @@ -80,7 +79,13 @@ int main(int argc, char ** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - loader.fillTree(tree); + { + FPoint particlePosition; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particlePosition); + tree.insert(particlePosition); + } + } counter.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; @@ -101,7 +106,7 @@ int main(int argc, char ** argv){ ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// - ValidateFMMAlgo<OctreeClass, ParticleClass, CellClass, ContainerClass, LeafClass>(&tree); + ValidateFMMAlgo<OctreeClass, CellClass, ContainerClass, LeafClass>(&tree); ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// diff --git a/Tests/Utils/testFmmAlgorithmPeriodic.cpp b/Tests/Utils/testFmmAlgorithmPeriodic.cpp index 60e03b3f8..4fad5a32f 100755 --- a/Tests/Utils/testFmmAlgorithmPeriodic.cpp +++ b/Tests/Utils/testFmmAlgorithmPeriodic.cpp @@ -30,9 +30,10 @@ #include "../../Src/Components/FSimpleLeaf.hpp" +#include "../../Src/Components/FTestParticleContainer.hpp" + #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Components/FTestParticle.hpp" #include "../../Src/Components/FTestCell.hpp" #include "../../Src/Components/FTestKernels.hpp" @@ -46,15 +47,14 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FTestParticle ParticleClass; typedef FTestCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FTestParticleContainer ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FTestKernels<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FTestKernels< CellClass, ContainerClass > KernelClass; - typedef FFmmAlgorithmPeriodic<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithmPeriodic<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test the FMM algorithm.\n"; ////////////////////////////////////////////////////////////// @@ -81,9 +81,16 @@ int main(int argc, char ** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - FRandomLoader<ParticleClass> loader(NbParticles); + FRandomLoader loader(NbParticles); OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); - loader.fillTree(tree); + + { + FPoint particlePosition; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particlePosition); + tree.insert(particlePosition); + } + } counter.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; @@ -108,17 +115,14 @@ int main(int argc, char ** argv){ { // Check that each particle has been summed with all other long long int counterNbPart = 0; - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - do{ - // on each leaf we should have the same number of particles - if(octreeIterator.getCurrentCell()->getDataUp() != octreeIterator.getCurrentListSrc()->getSize() ){ - std::cout << "Problem P2M Data up = " << octreeIterator.getCurrentCell()->getDataUp() << - " Size = " << octreeIterator.getCurrentListSrc()->getSize() << "\n"; + tree.forEachCellLeaf([&](CellClass* cell, LeafClass* leaf){ + if(cell->getDataUp() != leaf->getSrc()->getNbParticles() ){ + std::cout << "Problem P2M Data up = " << cell->getDataUp() << + " Size = " << leaf->getSrc()->getNbParticles() << "\n"; } // we also count the number of particles. - counterNbPart += octreeIterator.getCurrentListSrc()->getSize(); - } while(octreeIterator.moveRight()); + counterNbPart += leaf->getSrc()->getNbParticles(); + }); if( counterNbPart != NbParticles){ std::cout << "Problem global nb part, counter = " << counterNbPart << " created = " << NbParticles << std::endl; @@ -135,20 +139,14 @@ int main(int argc, char ** argv){ algo.repetitionsIntervals(&min, &max); std::cout << "Min is " << min << " Max is " << max << std::endl; - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - do{ - ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListTargets()); - - while( iter.hasNotFinished() ){ - if( NbParticlesEntireSystem - 1 != iter.data().getDataDown()){ + tree.forEachLeaf([&](LeafClass* leaf){ + for(int idxPart = 0 ; idxPart < leaf->getSrc()->getNbParticles() ; ++idxPart ){ + if( NbParticlesEntireSystem - 1 != leaf->getSrc()->getDataDown()[idxPart]){ std::cout << "P2P probleme, should be " << NbParticlesEntireSystem - 1 << - " iter.data().getDataDown() "<< iter.data().getDataDown() << std::endl; + " iter.data().getDataDown() "<< leaf->getSrc()->getDataDown()[idxPart] << std::endl; } - - iter.gotoNext(); } - } while(octreeIterator.moveRight()); + }); } ////////////////////////////////////////////////////////////////////////////////// diff --git a/Tests/Utils/testFmmAlgorithmProc.cpp b/Tests/Utils/testFmmAlgorithmProc.cpp index 56b567b6c..3c7b488d1 100755 --- a/Tests/Utils/testFmmAlgorithmProc.cpp +++ b/Tests/Utils/testFmmAlgorithmProc.cpp @@ -290,7 +290,7 @@ void print(OctreeClass* const valideTree){ -/** class has to extend {FExtendForces,FExtendPotential,FExtendPhysicalValue} +/** * Because we use fma loader it needs {FExtendPhysicalValue} */ class TestParticle : public FTestParticle, public FExtendPhysicalValue { diff --git a/Tests/Utils/testFmmAlgorithmTsm.cpp b/Tests/Utils/testFmmAlgorithmTsm.cpp index e6140ec7c..1355b4f19 100755 --- a/Tests/Utils/testFmmAlgorithmTsm.cpp +++ b/Tests/Utils/testFmmAlgorithmTsm.cpp @@ -29,11 +29,9 @@ #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Components/FTestParticle.hpp" #include "../../Src/Components/FTestCell.hpp" #include "../../Src/Components/FTestKernels.hpp" -#include "../../Src/Extensions/FExtendParticleType.hpp" #include "../../Src/Extensions/FExtendCellType.hpp" #include "../../Src/Core/FFmmAlgorithmTsm.hpp" @@ -43,29 +41,25 @@ #include "../../Src/Files/FRandomLoader.hpp" +#include "../../Src/Components/FTestParticleContainer.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that each particles is impacted each other particles */ - -class FTestParticleTsm : public FTestParticle, public FExtendParticleType { -}; - class FTestCellTsm: public FTestCell , public FExtendCellType{ }; - // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FTestParticleTsm ParticleClassTyped; typedef FTestCellTsm CellClassTyped; - typedef FVector<ParticleClassTyped> ContainerClassTyped; + typedef FTestParticleContainer ContainerClassTyped; - typedef FTypedLeaf<ParticleClassTyped, ContainerClassTyped > LeafClassTyped; - typedef FOctree<ParticleClassTyped, CellClassTyped, ContainerClassTyped , LeafClassTyped > OctreeClassTyped; - typedef FTestKernels<ParticleClassTyped, CellClassTyped, ContainerClassTyped > KernelClassTyped; + typedef FTypedLeaf< ContainerClassTyped > LeafClassTyped; + typedef FOctree< CellClassTyped, ContainerClassTyped , LeafClassTyped > OctreeClassTyped; + typedef FTestKernels< CellClassTyped, ContainerClassTyped > KernelClassTyped; - typedef FFmmAlgorithmThreadTsm<OctreeClassTyped, ParticleClassTyped, CellClassTyped, ContainerClassTyped, KernelClassTyped, LeafClassTyped > FmmClassTyped; + typedef FFmmAlgorithmThreadTsm<OctreeClassTyped, CellClassTyped, ContainerClassTyped, KernelClassTyped, LeafClassTyped > FmmClassTyped; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test the FMM algorithm.\n"; ////////////////////////////////////////////////////////////// @@ -78,7 +72,7 @@ int main(int argc, char ** argv){ ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// - FRandomLoaderTsm<ParticleClassTyped> loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1); + FRandomLoaderTsm loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1); OctreeClassTyped tree(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); ////////////////////////////////////////////////////////////////////////////////// @@ -87,7 +81,14 @@ int main(int argc, char ** argv){ std::cout << "Creating " << NbPart << " particles ..." << std::endl; counter.tic(); - loader.fillTree(tree); + { + FPoint particlePosition; + bool isTarget; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particlePosition, &isTarget); + tree.insert(particlePosition, isTarget); + } + } counter.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; @@ -110,8 +111,7 @@ int main(int argc, char ** argv){ ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// - ValidateFMMAlgo<OctreeClassTyped, ParticleClassTyped, CellClassTyped, ContainerClassTyped, LeafClassTyped>(&tree); - + ValidateFMMAlgo<OctreeClassTyped, CellClassTyped, ContainerClassTyped, LeafClassTyped>(&tree); return 0; } diff --git a/Tests/Utils/testFmmDemonstration.cpp b/Tests/Utils/testFmmDemonstration.cpp index 894c09313..c34ea474c 100755 --- a/Tests/Utils/testFmmDemonstration.cpp +++ b/Tests/Utils/testFmmDemonstration.cpp @@ -30,7 +30,6 @@ #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Components/FTestParticle.hpp" #include "../../Src/Components/FTestCell.hpp" #include "../../Src/Components/FTestKernels.hpp" @@ -38,6 +37,7 @@ #include "../../Src/Core/FFmmAlgorithmThread.hpp" +#include "../../Src/Components/FAbstractParticleContainer.hpp" #include "../../Src/Components/FBasicKernels.hpp" #include "../../Src/Files/FRandomLoader.hpp" @@ -46,51 +46,61 @@ class MyCell : public FBasicCell { }; -// My fack particle is a basic particle and! a index -// that correspond to the index in the user particles array -class MyFackParticle : public FBasicParticle { - int myIndex; +// My fack Container is simply saving the indexes of each +// particles (nothing more!) +class MyContainer : public FAbstractParticleContainer { + FVector<int> indexes; public: - MyFackParticle() : myIndex(0) { + template<typename... Args> + void push(const FPoint& /*inParticlePosition*/, const int newParticleIndex, Args ... /*args*/){ + indexes.push(newParticleIndex); } - void setIndex(const int inIndex){ - this->myIndex = inIndex; + + int getSize() const { + return indexes.getSize(); } - int getIndex() const{ - return this->myIndex; + + const FVector<int>& getIndexes() const{ + return indexes; } }; -// My leaf store the indexes of the particles it receives -// in a vector -class MyLeaf : public FAbstractLeaf<MyFackParticle, FVector<int> > { - FVector<int> indexes; +// My leaf process the particles and save only +// those where keepIt is true (during the push method) +class MyLeaf : public FAbstractLeaf< MyContainer > { + MyContainer particles; + public: - void push(const MyFackParticle& particle){ - indexes.push( particle.getIndex() ); + template<typename... Args> + void push(const FPoint& inParticlePosition, const bool keepIt, Args ... args){ + if(keepIt) particles.push(inParticlePosition, args...); } - FVector<int>* getSrc(){ - return &indexes; + MyContainer* getSrc(){ + return &particles; } - FVector<int>* getTargets(){ - return &indexes; + MyContainer* getTargets(){ + return &particles; } }; // My kernel actually does nothing except showing how to retreive data from an // array from the indexes vector giving by the leaf in the P2M -template< class ParticleClass, class CellClass, class ContainerClass> -class MyKernel : public FAbstractKernels<ParticleClass,CellClass,ContainerClass>{ - FBasicParticle*const realParticles; +template< class CellClass, class ContainerClass> +class MyKernel : public FAbstractKernels<CellClass,ContainerClass>{ + MortonIndex* indexForEachParticle; public: - MyKernel(FBasicParticle*const inRealParticles): realParticles(inRealParticles) { + MyKernel(const int inNbParticles): indexForEachParticle(new MortonIndex[inNbParticles]) { + memset(indexForEachParticle,0,sizeof(MortonIndex)*inNbParticles); } - void P2M(CellClass* const , const ContainerClass* const particlesIndexes) { - typename ContainerClass::ConstBasicIterator iter(*particlesIndexes); - while( iter.hasNotFinished() ){ - realParticles[iter.data()].getPosition(); - iter.gotoNext(); + ~MyKernel(){ + delete[] indexForEachParticle; + } + + void P2M(CellClass* const cell, const ContainerClass* const particles) { + for(int idxPart = 0 ; idxPart < particles->getSize() ; ++idxPart){ + // save the current morton index for each particles + indexForEachParticle[ particles->getIndexes()[idxPart] ] = cell->getMortonIndex(); } } @@ -121,14 +131,15 @@ public: int main(int argc, char ** argv){ - typedef MyFackParticle ParticleClass; + // Custom data structure here typedef MyCell CellClass; - typedef FVector<int> ContainerClass; + typedef MyContainer ContainerClass; typedef MyLeaf LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - typedef MyKernel<ParticleClass, CellClass, ContainerClass > KernelClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + // Standard things here + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + typedef MyKernel< CellClass, ContainerClass > KernelClass; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; ////////////////////////////////////////////////////////////// ///////////////////////What we do///////////////////////////// @@ -146,9 +157,8 @@ int main(int argc, char ** argv){ ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// - FRandomLoader<ParticleClass> loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1); + FRandomLoader loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1); OctreeClass tree(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); - FBasicParticle*const realsParticles = new FBasicParticle[NbPart]; ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// @@ -157,17 +167,19 @@ int main(int argc, char ** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); + FPoint*const realsParticlesPositions = new FPoint[NbPart]; { - ParticleClass particleToFill; + FPoint particlePosition; + bool keepIt; for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ // get a random position - loader.fillParticle(particleToFill); - // put the index inside - particleToFill.setIndex(idxPart); + loader.fillParticle(&particlePosition); + // let say we remove 1/5 particles + keepIt = (idxPart%5); // insert in the tree - tree.insert(particleToFill); - // copy in the array - realsParticles[idxPart].setPosition(particleToFill.getPosition()); + tree.insert(particlePosition, keepIt, idxPart); + // save the position + realsParticlesPositions[idxPart] = particlePosition; } } @@ -183,15 +195,13 @@ int main(int argc, char ** argv){ OctreeClass::Iterator octreeIterator(&tree); octreeIterator.gotoBottomLeft(); do{ - ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets()); + FVector<int>::ConstBasicIterator iter(octreeIterator.getCurrentListTargets()->getIndexes()); const MortonIndex indexAtThisLeaf = octreeIterator.getCurrentGlobalIndex(); while( iter.hasNotFinished() ){ - std::cout << "Particles with index " << iter.data() << " has a morton index of " << indexAtThisLeaf << std::endl; - - const FPoint& particlePosition = realsParticles[iter.data()].getPosition(); - std::cout << "\t The real position of this particle is (" << particlePosition.getX() << ";" << particlePosition.getY() << ";" << particlePosition.getZ() << ")" << std::endl; - + std::cout << "Particles with index " << iter.data() << + " has a morton index of " << indexAtThisLeaf << std::endl; + std::cout << " it real position was " << realsParticlesPositions[iter.data()] << std::endl; iter.gotoNext(); } } while(octreeIterator.moveRight()); @@ -205,7 +215,7 @@ int main(int argc, char ** argv){ std::cout << "Working on particles ..." << std::endl; counter.tic(); - KernelClass kernels(realsParticles); + KernelClass kernels(NbPart); FmmClass algo(&tree,&kernels); algo.execute(); @@ -215,7 +225,7 @@ int main(int argc, char ** argv){ ////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////// - delete [] realsParticles; + delete [] realsParticlesPositions; return 0; } diff --git a/Tests/Utils/testLoader.cpp b/Tests/Utils/testLoader.cpp index d35e95ee7..d80126edc 100755 --- a/Tests/Utils/testLoader.cpp +++ b/Tests/Utils/testLoader.cpp @@ -29,13 +29,14 @@ #include "../../Src/Utils/FAssertable.hpp" #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Components/FBasicParticle.hpp" #include "../../Src/Components/FBasicCell.hpp" #include "../../Src/Components/FSimpleLeaf.hpp" #include "../../Src/Files/FBasicLoader.hpp" +#include "../../Src/Components/FBasicParticleContainer.hpp" + /** * In this file we show an example of FBasicLoader use * Inserting 2000000 particles ... @@ -45,9 +46,9 @@ */ int main(int argc, char ** argv){ - typedef FVector<FBasicParticle> ContainerClass; - typedef FSimpleLeaf<FBasicParticle, ContainerClass > LeafClass; - typedef FOctree<FBasicParticle, FBasicCell, ContainerClass , LeafClass > OctreeClass; + typedef FBasicParticleContainer<0> ContainerClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< FBasicCell, ContainerClass , LeafClass > OctreeClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable is useless to execute.\n"; std::cout << ">> It is only interesting to wath the code to understand\n"; @@ -61,7 +62,7 @@ int main(int argc, char ** argv){ std::cout << "Opening : " << filename << "\n"; // open basic particles loader - FBasicLoader<FBasicParticle> loader(filename); + FBasicLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << "is missing\n"; return 1; @@ -76,7 +77,11 @@ int main(int argc, char ** argv){ std::cout << "Inserting " << loader.getNumberOfParticles() << " particles ..." << std::endl; counter.tic(); - loader.fillTree(tree); + FPoint particlePosition; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particlePosition); + tree.insert(particlePosition); + } counter.tac(); std::cout << "Done " << "(" << counter.elapsed() << ")." << std::endl; diff --git a/Tests/Utils/testLoaderFMA.cpp b/Tests/Utils/testLoaderFMA.cpp index 5f39cf62a..fad2028df 100755 --- a/Tests/Utils/testLoaderFMA.cpp +++ b/Tests/Utils/testLoaderFMA.cpp @@ -29,14 +29,13 @@ #include "../../Src/Utils/FAssertable.hpp" #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Components/FFmaParticle.hpp" #include "../../Src/Components/FBasicCell.hpp" #include "../../Src/Components/FSimpleLeaf.hpp" #include "../../Src/Files/FFmaLoader.hpp" -// Compile by : g++ testLoaderFMA.cpp ../../Src/Utils/FDebug.cpp ../../Src/Utils/FTrace.cpp -O2 -o testLoaderFMA.exe +#include "../../Src/Components/FBasicParticleContainer.hpp" /** @@ -48,9 +47,9 @@ */ int main(int argc, char ** argv ){ - typedef FVector<FFmaParticle> ContainerClass; - typedef FSimpleLeaf<FFmaParticle, ContainerClass > LeafClass; - typedef FOctree<FFmaParticle, FBasicCell, ContainerClass , LeafClass > OctreeClass; + typedef FBasicParticleContainer<1> ContainerClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< FBasicCell, ContainerClass , LeafClass > OctreeClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable is useless to execute.\n"; std::cout << ">> It is only interesting to wath the code to understand\n"; @@ -63,7 +62,7 @@ int main(int argc, char ** argv ){ std::cout << "Opening : " << filename << "\n"; // open basic particles loader - FFmaLoader<FFmaParticle> loader(filename); + FFmaLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << "is missing\n"; return 1; @@ -78,7 +77,12 @@ int main(int argc, char ** argv ){ std::cout << "Inserting " << loader.getNumberOfParticles() << " particles ..." << std::endl; counter.tic(); - loader.fillTree(tree); + FPoint particlePosition; + FReal physicalValue = 0.0; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition,physicalValue); + } counter.tac(); std::cout << "Done " << "(" << counter.elapsed() << ")." << std::endl; diff --git a/Tests/Utils/testLoaderFMATsm.cpp b/Tests/Utils/testLoaderFMATsm.cpp index 4288c7e21..747150d33 100755 --- a/Tests/Utils/testLoaderFMATsm.cpp +++ b/Tests/Utils/testLoaderFMATsm.cpp @@ -28,31 +28,22 @@ #include "../../Src/Utils/FAssertable.hpp" #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Components/FFmaParticle.hpp" #include "../../Src/Components/FBasicCell.hpp" -#include "../../Src/Extensions/FExtendParticleType.hpp" - -#include "../../Src/Components/FSimpleLeaf.hpp" +#include "../../Src/Components/FTypedLeaf.hpp" #include "../../Src/Files/FFmaTsmLoader.hpp" +#include "../../Src/Components/FBasicParticleContainer.hpp" #include "../../Src/Utils/FParameters.hpp" -/** - * In this file we show an example of FFmaLoader use - */ - -class ParticleTsm : public FFmaParticle, public FExtendParticleType { -}; - int main(int argc, char ** argv ){ - typedef FVector<ParticleTsm> ContainerClass; - typedef FSimpleLeaf<ParticleTsm, ContainerClass > LeafClass; - typedef FOctree<ParticleTsm, FBasicCell, ContainerClass , LeafClass > OctreeClass; + typedef FBasicParticleContainer<1> ContainerClass; + typedef FTypedLeaf< ContainerClass > LeafClass; + typedef FOctree< FBasicCell, ContainerClass , LeafClass > OctreeClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable is useless to execute.\n"; std::cout << ">> It is only interesting to wath the code to understand\n"; @@ -65,7 +56,7 @@ int main(int argc, char ** argv ){ std::cout << "Opening : " << filename << "\n"; // open basic particles loader - FFmaTsmLoader<ParticleTsm> loader(filename); + FFmaTsmLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << "is missing\n"; return 1; @@ -79,7 +70,13 @@ int main(int argc, char ** argv ){ std::cout << "Inserting " << loader.getNumberOfParticles() << " particles ..." << std::endl; counter.tic(); - loader.fillTree(tree); + FPoint particlePosition; + FReal physicalValue = 0.0; + bool isTarget; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particlePosition,&physicalValue, &isTarget); + tree.insert(particlePosition, isTarget, physicalValue); + } counter.tac(); std::cout << "Done " << "(" << counter.elapsed() << ")." << std::endl; diff --git a/Tests/Utils/testMemStats.cpp b/Tests/Utils/testMemStats.cpp index ccaa1aade..b794ab08f 100755 --- a/Tests/Utils/testMemStats.cpp +++ b/Tests/Utils/testMemStats.cpp @@ -29,17 +29,17 @@ #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Components/FTestParticle.hpp" #include "../../Src/Components/FTestCell.hpp" #include "../../Src/Components/FTestKernels.hpp" #include "../../Src/Kernels/Spherical/FSphericalKernel.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" #include "../../Src/Components/FSimpleLeaf.hpp" #include "../../Src/Core/FFmmAlgorithm.hpp" +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" + /** This program show an example of use of * the fmm basic algo * it also check that each particles is impacted each other particles @@ -48,19 +48,16 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ { - //typedef FTestParticle ParticleClass; - //typedef FTestCell CellClass; - typedef FSphericalParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainer ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; - //typedef FTestKernels<ParticleClass, CellClass, ContainerClass > KernelClass; - typedef FSphericalKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; + //typedef FTestKernels< CellClass, ContainerClass > KernelClass; + typedef FSphericalKernel< CellClass, ContainerClass > KernelClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test the FMM algorithm.\n"; ////////////////////////////////////////////////////////////// @@ -90,10 +87,11 @@ int main(int argc, char ** argv){ counter.tic(); { - ParticleClass particleToFill; + FPoint particlePosition; + FReal physicalValue = 0.10; for(int idxPart = 0 ; idxPart < NbPart ; ++idxPart){ - particleToFill.setPosition(FReal(rand())/FRandMax,FReal(rand())/FRandMax,FReal(rand())/FRandMax); - tree.insert(particleToFill); + particlePosition.setPosition(FReal(rand())/FRandMax,FReal(rand())/FRandMax,FReal(rand())/FRandMax); + tree.insert(particlePosition, physicalValue); } } diff --git a/Tests/Utils/testMortonIndex.cpp b/Tests/Utils/testMortonIndex.cpp deleted file mode 100755 index 14bf6464a..000000000 --- a/Tests/Utils/testMortonIndex.cpp +++ /dev/null @@ -1,194 +0,0 @@ -// =================================================================================== -// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner -// olivier.coulaud@inria.fr, berenger.bramas@inria.fr -// This software is a computer program whose purpose is to compute the FMM. -// -// This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". -// "http://www.gnu.org/licenses". -// =================================================================================== - -#include <iostream> - -#include <cstdio> -#include <cstdlib> -#include <string> -#include <iostream> -#include <iomanip> -#include <vector> -#include <algorithm> - -#include "../../Src/Utils/FTic.hpp" - -#include "../../Src/Containers/FOctree.hpp" -#include "../../Src/Containers/FVector.hpp" - -#include "../../Src/Components/FBasicParticle.hpp" - -#include "../../Src/Components/FBasicCell.hpp" - -#include "../../Src/Core/FFmmAlgorithm.hpp" -#include "../../Src/Core/FFmmAlgorithmThread.hpp" - -#include "../../Src/Components/FSimpleLeaf.hpp" - -#include "../../Src/Utils/FGlobal.hpp" -#include "../../Src/Utils/FParameters.hpp" - -#include "../../Src/Files/FHLoader.hpp" - -static const int PrintPrecision = 6; - -/** Basic function to convert a morton index in decimal string */ -std::string MortonToBinary(MortonIndex index, int level){ - std::string str; - int bits = 1 << ((level * 3) - 1); - int dim = 0; - while(bits){ - if(index & bits) str.append("1"); - else str.append("0"); - bits >>= 1; - // we put a dot each 3 values - if(++dim == 3){ - str.append("."); - dim = 0; - } - } - return str; -} -/** This program show an example of use of - * the moront indexing from a file - */ -struct AtomIndex { - int globalIndex ; - MortonIndex indexMorton; -}; - -bool compareIndex(const AtomIndex& a, const AtomIndex& b){ - return (a.indexMorton < b.indexMorton); -} - -class Particle : public FBasicParticle { - char data ; - AtomIndex index ; - // -public: - char getData() const{ - return data; - } - void setData(const char inData){ - this->data = inData; - } - - MortonIndex mortonIndex() const{ - return index.indexMorton; - } - void setMortonIndex(const MortonIndex inIndex) { - index.indexMorton = inIndex; - } - - int globalIndex() const{ - return index.globalIndex; - } - void setGlobalIndex(const int inIndex) { - index.globalIndex = inIndex; - } - -}; - - -// Simply create particles and try the kernels -int main(int argc, char ** argv){ - typedef FVector<Particle> ContainerClass; - typedef FSimpleLeaf<Particle, ContainerClass > LeafClass; - typedef FOctree<Particle, FBasicCell, ContainerClass , LeafClass > OctreeClass; - ///////////////////////What we do///////////////////////////// - std::cout << ">> This executable has to be used to know the box used.\n"; - ////////////////////////////////////////////////////////////// - - const int NbLevels = FParameters::getValue(argc,argv,"-h", 5); - const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3); - FTic counter; - const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/testMortonIndex.txt"); - std::cout << "Opening : " << filename << "\n"; - - FHLoader<Particle> loader(filename); - if(!loader.isOpen() ){ - std::cout << "Loader Error, " << filename << " is missing\n"; - return 1; - } - - // ----------------------------------------------------- - - OctreeClass tree(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); - - // ----------------------------------------------------- - - std::cout << "Creating and inserting " << loader.getNumberOfParticles() << " particles ..." << std::endl; - std::cout << "Width of box is " << loader.getBoxWidth() << std::endl; - std::cout << "Center of box is x " << loader.getCenterOfBox().getX() << " y " << loader.getCenterOfBox().getY() << " z " << loader.getCenterOfBox().getZ()<< std::endl; - counter.tic(); - { - Particle particle; - for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - loader.fillParticle(particle); - particle.setGlobalIndex( idxPart+1 ); - particle.setMortonIndex( -1 ); - tree.insert(particle); - } - } - counter.tac(); - std::cout << "Done " << "(" << counter.elapsed() << "s)." << std::endl; - - // ----------------------------------------------------- - - counter.tic(); - int idx = 1 ; - std::vector<AtomIndex> permutation( int(loader.getNumberOfParticles()) ) ; - - { // print indexes - - // ----------------------------------------------------- - - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - idx = 0; - do{ - const MortonIndex currentIndex = octreeIterator.getCurrentGlobalIndex(); - // std::cout << "Current Morton Index : " << currentIndex << " or in binary " << MortonToBinary(currentIndex,NbLevels-1) << std::endl; - // std::cout << "Particles :" << std::endl; - - ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListTargets()); - while( iter.hasNotFinished() ){ - iter.data().setMortonIndex(currentIndex); - // iter.data().mortonIndex() = currentIndex ; - permutation[idx].indexMorton = currentIndex ; - permutation[idx].globalIndex = idx + 1; - ++idx; - // printf("\tx = %e y = %e z = %e data = %c\n",iter.value()->getPosition().getX(),iter.value()->getPosition().getY(),iter.value()->getPosition().getZ(),iter.value()->getData()); - // std::cout << " " <<iter.value()->globalIndex() << " " << (int) iter.value()->mortonIndex() << std::endl; - std::cout << " " << iter.data().getData() - << std::setprecision(PrintPrecision) - << std::setw(15) << iter.data().getPosition().getX() - << std::setw(15) << iter.data().getPosition().getY() - << std::setw(15) <<iter.data().getPosition().getZ() - << std::endl; - iter.gotoNext(); - } - - } while(octreeIterator.moveRight()); - } - - - - return 0; -} - - - diff --git a/Tests/Utils/testOctree.cpp b/Tests/Utils/testOctree.cpp index be7093fb2..b2c6e5271 100755 --- a/Tests/Utils/testOctree.cpp +++ b/Tests/Utils/testOctree.cpp @@ -29,7 +29,7 @@ #include "../../Src/Utils/FAssertable.hpp" #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Components/FBasicParticle.hpp" +#include "../../Src/Components/FBasicParticleContainer.hpp" #include "../../Src/Components/FBasicCell.hpp" #include "../../Src/Components/FSimpleLeaf.hpp" @@ -40,9 +40,9 @@ */ int main(int argc, char ** argv){ - typedef FVector<FBasicParticle> ContainerClass; - typedef FSimpleLeaf<FBasicParticle, ContainerClass > LeafClass; - typedef FOctree<FBasicParticle, FBasicCell, ContainerClass , LeafClass > OctreeClass; + typedef FBasicParticleContainer<0> ContainerClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< FBasicCell, ContainerClass , LeafClass > OctreeClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable is useless to execute.\n"; std::cout << ">> It is only interesting to wath the code to understand\n"; @@ -51,14 +51,18 @@ int main(int argc, char ** argv){ const int NbPart = FParameters::getValue(argc,argv,"-nb", 2000000); FTic counter; - FRandomLoader<FBasicParticle> loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1); + FRandomLoader loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1); OctreeClass tree(10, 3, loader.getBoxWidth(), loader.getCenterOfBox()); // ----------------------------------------------------- std::cout << "Creating and inserting " << NbPart << " particles ..." << std::endl; counter.tic(); - loader.fillTree(tree); + FPoint particlePosition; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particlePosition); + tree.insert(particlePosition); + } counter.tac(); std::cout << "Done " << "(" << counter.elapsed() << ")." << std::endl; diff --git a/Tests/Utils/testOctreeFuncteur.cpp b/Tests/Utils/testOctreeFuncteur.cpp index 7455db6d1..07f6909bc 100644 --- a/Tests/Utils/testOctreeFuncteur.cpp +++ b/Tests/Utils/testOctreeFuncteur.cpp @@ -29,7 +29,7 @@ #include "../../Src/Utils/FAssertable.hpp" #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Components/FBasicParticle.hpp" +#include "../../Src/Components/FBasicParticleContainer.hpp" #include "../../Src/Components/FBasicCell.hpp" #include "../../Src/Components/FSimpleLeaf.hpp" @@ -40,9 +40,10 @@ */ int main(int argc, char ** argv){ - typedef FVector<FBasicParticle> ContainerClass; - typedef FSimpleLeaf<FBasicParticle, ContainerClass > LeafClass; - typedef FOctree<FBasicParticle, FBasicCell, ContainerClass , LeafClass > OctreeClass; + typedef FBasicCell CellClass; + typedef FBasicParticleContainer<0> ContainerClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree<CellClass, ContainerClass , LeafClass > OctreeClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable is useless to execute.\n"; std::cout << ">> It is only interesting to wath the code to understand\n"; @@ -51,14 +52,20 @@ int main(int argc, char ** argv){ const int NbPart = FParameters::getValue(argc,argv,"-nb", 2000); FTic counter; - FRandomLoader<FBasicParticle> loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1); + FRandomLoader loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1); OctreeClass tree(10, 3, loader.getBoxWidth(), loader.getCenterOfBox()); // ----------------------------------------------------- std::cout << "Creating and inserting " << NbPart << " particles ..." << std::endl; counter.tic(); - loader.fillTree(tree); + { + FPoint particlePosition; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + loader.fillParticle(&particlePosition); + tree.insert(particlePosition); + } + } counter.tac(); std::cout << "Done " << "(" << counter.elapsed() << ")." << std::endl; @@ -67,19 +74,19 @@ int main(int argc, char ** argv){ // Call a function on each leaf long nbParticles = 0; tree.forEachLeaf([&](LeafClass* leaf){ - nbParticles += leaf->getSrc()->getSize(); + nbParticles += leaf->getSrc()->getNbParticles(); }); std::cout << "There are " << nbParticles << " particles " << std::endl; // Call a function on each cell long nbCells = 0; - tree.forEachCell([&nbCells](FBasicCell* /*cell*/){ + tree.forEachCell([&nbCells](CellClass* /*cell*/){ nbCells += 1; }); std::cout << "There are " << nbCells << " cells " << std::endl; // To get cell and particles at leaf level - tree.forEachCellLeaf([&](FBasicCell* /*cell*/, LeafClass* /*leaf*/){ + tree.forEachCellLeaf([&](CellClass* /*cell*/, LeafClass* /*leaf*/){ }); return 0; diff --git a/Tests/Utils/testOctreeIter.cpp b/Tests/Utils/testOctreeIter.cpp index 4ae66fbef..6c6fc6f41 100755 --- a/Tests/Utils/testOctreeIter.cpp +++ b/Tests/Utils/testOctreeIter.cpp @@ -30,7 +30,7 @@ #include "../../Src/Utils/FAssertable.hpp" #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Components/FBasicParticle.hpp" +#include "../../Src/Components/FBasicParticleContainer.hpp" #include "../../Src/Components/FBasicCell.hpp" #include "../../Src/Utils/FTic.hpp" @@ -41,9 +41,9 @@ */ int main(int argc, char ** argv){ - typedef FVector<FBasicParticle> ContainerClass; - typedef FSimpleLeaf<FBasicParticle, ContainerClass > LeafClass; - typedef FOctree<FBasicParticle, FBasicCell, ContainerClass , LeafClass > OctreeClass; + typedef FBasicParticleContainer<0> ContainerClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< FBasicCell, ContainerClass , LeafClass > OctreeClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable is useless to execute.\n"; std::cout << ">> It is only interesting to wath the code to understand\n"; @@ -66,7 +66,7 @@ int main(int argc, char ** argv){ std::cout << "Creating and inserting " << NbPart << " particles ..." << std::endl; counterTime.tic(); { - FBasicParticle particle; + FPoint particle; for(long idxPart = 0 ; idxPart < NbPart ; ++idxPart){ particle.setPosition(FReal(rand())/FRandMax,FReal(rand())/FRandMax,FReal(rand())/FRandMax); tree.insert(particle); @@ -77,7 +77,7 @@ int main(int argc, char ** argv){ // ----------------------------------------------------- { - std::cout << "Itering on particles ..." << std::endl; + std::cout << "Itering on Cells ..." << std::endl; counterTime.tic(); OctreeClass::Iterator octreeIterator(&tree); @@ -87,7 +87,7 @@ int main(int argc, char ** argv){ do{ ++counter; //counter += octreeIterator.getCurrentList()->getSize(); - } while(octreeIterator.moveRight()); + } while(octreeIterator.moveRight()); octreeIterator.moveUp(); octreeIterator.gotoLeft(); std::cout << "Cells at this level " << counter << " ...\n"; diff --git a/Tests/Utils/testOctreeRearrange.cpp b/Tests/Utils/testOctreeRearrange.cpp index 0bef5d1ee..3123d8195 100755 --- a/Tests/Utils/testOctreeRearrange.cpp +++ b/Tests/Utils/testOctreeRearrange.cpp @@ -29,20 +29,62 @@ #include "../../Src/Utils/FPoint.hpp" -#include "../../Src/Components/FTestParticle.hpp" -#include "../../Src/Components/FTestCell.hpp" +#include "../../Src/Components/FBasicParticleContainer.hpp" +#include "../../Src/Components/FBasicCell.hpp" #include "../../Src/Arranger/FOctreeArranger.hpp" +template <class ContainerClass> +class Extractor { + struct Particle{ + FPoint position; + FReal physicalValue; + FReal forces[3]; + FReal potential; + }; + + FVector<Particle> savedParticles; + +public: + void extractParticles(const ContainerClass* containers, const int indexesToExtract[], const int nbToExtract){ + //const FReal*const physicalValues = containers->getPhysicalValues(); + const FReal*const positionsX = containers->getPositions()[0]; + const FReal*const positionsY = containers->getPositions()[1]; + const FReal*const positionsZ = containers->getPositions()[2]; + //const FReal*const forcesX = containers->getForcesX(); + //const FReal*const forcesY = containers->getForcesY(); + //const FReal*const forcesZ = containers->getForcesZ(); + //const FReal*const potentials = containers->getPotentials(); + + for(int idxPart = 0 ; idxPart < nbToExtract ; ++ idxPart){ + const int idxExtract = indexesToExtract[idxPart]; + Particle part; + part.position.setPosition( positionsX[idxExtract],positionsY[idxExtract],positionsZ[idxExtract]); + //part.physicalValue = physicalValues[idxExtract]; + //part.forces[0] = forcesX[idxExtract]; + //part.forces[1] = forcesY[idxExtract]; + //part.forces[2] = forcesZ[idxExtract]; + //part.potential = potentials[idxExtract]; + } + } + + template <class OctreeClass> + void reinsertInTree(OctreeClass* tree){ + for(int idxPart = 0 ; idxPart < savedParticles.getSize() ; ++idxPart){ + const Particle part = savedParticles[idxPart]; + tree->insert(part.position/*, part.physicalValue, part.forces[0], + part.forces[1],part.forces[2],part.potential*/); + } + } +}; // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FTestParticle ParticleClass; - typedef FTestCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FBasicCell CellClass; + typedef FBasicParticleContainer<0> ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to test the FMM algorithm.\n"; @@ -75,7 +117,7 @@ int main(int argc, char ** argv){ { - FTestParticle particleToFill; + FPoint particleToFill; for(int idxPart = 0 ; idxPart < NbPart ; ++idxPart){ particleToFill.setPosition( (BoxWidth*FReal(rand())/FRandMax) + (BoxCenter-(BoxWidth/2)), @@ -94,19 +136,15 @@ int main(int argc, char ** argv){ std::cout << "Working on particles ..." << std::endl; counter.tic(); - { // Check that each particle has been summed with all other + { // Create new position for each particles OctreeClass::Iterator octreeIterator(&tree); octreeIterator.gotoBottomLeft(); do{ - ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListTargets()); - - while( iter.hasNotFinished() ){ - iter.data().setPosition( - (BoxWidth*FReal(rand())/FRandMax) + (BoxCenter-(BoxWidth/2)), - (BoxWidth*FReal(rand())/FRandMax) + (BoxCenter-(BoxWidth/2)), - (BoxWidth*FReal(rand())/FRandMax) + (BoxCenter-(BoxWidth/2))); - - iter.gotoNext(); + ContainerClass* particles = octreeIterator.getCurrentListTargets(); + for(int idxPart = 0; idxPart < particles->getNbParticles() ; ++idxPart){ + particles->getWPositions()[0][idxPart] = (BoxWidth*FReal(rand())/FRandMax) + (BoxCenter-(BoxWidth/2)); + particles->getWPositions()[1][idxPart] = (BoxWidth*FReal(rand())/FRandMax) + (BoxCenter-(BoxWidth/2)); + particles->getWPositions()[2][idxPart] = (BoxWidth*FReal(rand())/FRandMax) + (BoxCenter-(BoxWidth/2)); } } while(octreeIterator.moveRight()); } @@ -121,7 +159,7 @@ int main(int argc, char ** argv){ std::cout << "Arrange ..." << std::endl; counter.tic(); - FOctreeArranger<OctreeClass, ContainerClass, ParticleClass> arrange(&tree); + FOctreeArranger<OctreeClass, ContainerClass, Extractor<ContainerClass> > arrange(&tree); arrange.rearrange(); counter.tac(); @@ -139,21 +177,24 @@ int main(int argc, char ** argv){ OctreeClass::Iterator octreeIterator(&tree); octreeIterator.gotoBottomLeft(); do{ - ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListTargets()); - const MortonIndex leafIndex = octreeIterator.getCurrentGlobalIndex(); - while( iter.hasNotFinished() ){ - const MortonIndex particleIndex = tree.getMortonFromPosition( iter.data().getPosition() ); + ContainerClass* particles = octreeIterator.getCurrentListTargets(); + for(int idxPart = 0; idxPart < particles->getNbParticles() ; ++idxPart){ + const FPoint particlePosition( particles->getWPositions()[0][idxPart], + particles->getWPositions()[1][idxPart], + particles->getWPositions()[2][idxPart]); + + const MortonIndex particleIndex = tree.getMortonFromPosition( particlePosition ); if( leafIndex != particleIndex){ std::cout << "Index problem, should be " << leafIndex << " particleIndex "<< particleIndex << std::endl; } - iter.gotoNext(); } - counterPart += octreeIterator.getCurrentListTargets()->getSize(); - if(octreeIterator.getCurrentListTargets()->getSize() == 0){ + + counterPart += octreeIterator.getCurrentListTargets()->getNbParticles(); + if(octreeIterator.getCurrentListTargets()->getNbParticles() == 0){ std::cout << "Problem, leaf is empty at index " << leafIndex << std::endl; } } while(octreeIterator.moveRight()); diff --git a/Tests/Utils/testStatsTree.cpp b/Tests/Utils/testStatsTree.cpp index 470f7b86f..7f0893737 100755 --- a/Tests/Utils/testStatsTree.cpp +++ b/Tests/Utils/testStatsTree.cpp @@ -25,10 +25,6 @@ #include "../../Src/Containers/FOctree.hpp" #include "../../Src/Containers/FVector.hpp" -#include "../../Src/Components/FFmaParticle.hpp" -#include "../../Src/Extensions/FExtendForces.hpp" -#include "../../Src/Extensions/FExtendPotential.hpp" - #include "../../Src/Components/FBasicCell.hpp" #include "../../Src/Core/FFmmAlgorithm.hpp" @@ -41,6 +37,8 @@ #include "../../Src/Files/FFmaLoader.hpp" +#include "../../Src/Components/FBasicParticleContainer.hpp" + /** This program show an example of use of * the fmm basic algo @@ -51,9 +49,9 @@ // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FVector<FFmaParticle> ContainerClass; - typedef FSimpleLeaf<FFmaParticle, ContainerClass > LeafClass; - typedef FOctree<FFmaParticle, FBasicCell, ContainerClass , LeafClass > OctreeClass; + typedef FBasicParticleContainer<0> ContainerClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< FBasicCell, ContainerClass , LeafClass > OctreeClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to show some stat about the tree.\n"; ////////////////////////////////////////////////////////////// @@ -65,7 +63,7 @@ int main(int argc, char ** argv){ const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; - FFmaLoader<FFmaParticle> loader(filename); + FFmaLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << " is missing\n"; return 1; @@ -81,8 +79,12 @@ int main(int argc, char ** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - - loader.fillTree(tree); + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint particlePosition; + FReal physicalValue; + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition ); + } counter.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; @@ -101,7 +103,7 @@ int main(int argc, char ** argv){ OctreeClass::Iterator octreeIterator(&tree); octreeIterator.gotoBottomLeft(); do{ - averageParticles += FReal(octreeIterator.getCurrentListTargets()->getSize()); + averageParticles += FReal(octreeIterator.getCurrentListTargets()->getNbParticles()); ++nbLeafs; } while(octreeIterator.moveRight()); averageParticles /= FReal(nbLeafs); @@ -116,7 +118,7 @@ int main(int argc, char ** argv){ OctreeClass::Iterator octreeIterator(&tree); octreeIterator.gotoBottomLeft(); do{ - varianceParticles += FReal(octreeIterator.getCurrentListTargets()->getSize() * octreeIterator.getCurrentListTargets()->getSize()); + varianceParticles += FReal(octreeIterator.getCurrentListTargets()->getNbParticles() * octreeIterator.getCurrentListTargets()->getNbParticles()); ++nbLeafs; } while(octreeIterator.moveRight()); varianceParticles /= FReal(nbLeafs); diff --git a/Tests/Utils/testTreeIO.cpp b/Tests/Utils/testTreeIO.cpp index 87f821d80..ff18fa449 100755 --- a/Tests/Utils/testTreeIO.cpp +++ b/Tests/Utils/testTreeIO.cpp @@ -30,20 +30,18 @@ #include "../../Src/Files/FTreeIO.hpp" #include "../../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp" #include "../../Src/Components/FSimpleLeaf.hpp" - +#include "../../Src/Kernels/P2P/FP2PParticleContainer.hpp" // Simply create particles and try the kernels int main(int argc, char ** argv){ - typedef FSphericalParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainer ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; ///////////////////////What we do///////////////////////////// std::cout << ">> This executable has to be used to load or retrieve an entier tree.\n"; @@ -55,7 +53,7 @@ int main(int argc, char ** argv){ const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma"); std::cout << "Opening : " << filename << "\n"; - FFmaLoader<ParticleClass> loader(filename); + FFmaLoader loader(filename); if(!loader.isOpen()){ std::cout << "Loader Error, " << filename << " is missing\n"; return 1; @@ -71,7 +69,12 @@ int main(int argc, char ** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - loader.fillTree(tree); + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint particlePosition; + FReal physicalValue = 0.0; + loader.fillParticle(&particlePosition,&physicalValue); + tree.insert(particlePosition, physicalValue ); + } counter.tac(); std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl; @@ -80,13 +83,13 @@ int main(int argc, char ** argv){ std::cout << "Save tree ..." << std::endl; - FTreeIO::Save<OctreeClass, CellClass, ParticleClass, ContainerClass >("/tmp/tree.data", tree); + FTreeIO::Save<OctreeClass, CellClass, LeafClass, ContainerClass >("/tmp/tree.data", tree); // ----------------------------------------------------- std::cout << "Load tree ..." << std::endl; - FTreeIO::Load<OctreeClass, CellClass, ParticleClass, ContainerClass >("/tmp/tree.data", tree); + FTreeIO::Load<OctreeClass, CellClass, LeafClass, ContainerClass >("/tmp/tree.data", tree); return 0; } diff --git a/UTests/utestChebyshevDirect.cpp b/UTests/utestChebyshevDirect.cpp index 73d850dfb..566547be4 100755 --- a/UTests/utestChebyshevDirect.cpp +++ b/UTests/utestChebyshevDirect.cpp @@ -31,30 +31,19 @@ #include "FUTester.hpp" -#include "../Src/Kernels/Chebyshev/FChebParticle.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" + #include "../Src/Kernels/Chebyshev/FChebLeaf.hpp" #include "../Src/Kernels/Chebyshev/FChebCell.hpp" #include "../Src/Kernels/Chebyshev/FChebMatrixKernel.hpp" #include "../Src/Kernels/Chebyshev/FChebKernel.hpp" #include "../Src/Kernels/Chebyshev/FChebSymKernel.hpp" +#include "../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp" /* In this test we compare the spherical fmm results and the direct results. */ -/** We need to know the position of the particle in the array */ -class IndexedParticle : public FChebParticle { - int index; -public: - IndexedParticle(): index(-1){} - - int getIndex() const{ - return index; - } - void setIndex( const int inIndex ){ - index = inIndex; - } -}; /** the test class * @@ -65,7 +54,7 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { // The tests! /////////////////////////////////////////////////////////// - template <class ParticleClass, class CellClass, class ContainerClass, class KernelClass, class MatrixKernelClass, + template <class CellClass, class ContainerClass, class KernelClass, class MatrixKernelClass, class LeafClass, class OctreeClass, class FmmClass> void RunTest(const FReal epsilon) { // Warning in make test the exec dir it Build/UTests @@ -73,7 +62,7 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { const char* const filename = (sizeof(FReal) == sizeof(float))? "../../Data/utestDirect.bin.fma.single": "../../Data/utestDirect.bin.fma.double"; - FFmaBinLoader<ParticleClass> loader(filename); + FFmaBinLoader loader(filename); if(!loader.isOpen()){ Print("Cannot open particles file."); uassert(false); @@ -87,13 +76,31 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { //const FReal epsilon = FReal(1e-5); // Create octree - OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); - ParticleClass* const particles = new ParticleClass[loader.getNumberOfParticles()]; - for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - loader.fillParticle(particles[idxPart]); - particles[idxPart].setIndex( idxPart ); - tree.insert(particles[idxPart]); - } + struct TestParticle{ + FPoint position; + FReal forces[3]; + FReal physicalValue; + FReal potential; + }; + + TestParticle* const particles = new TestParticle[loader.getNumberOfParticles()]; + + // Create octree + OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint position; + FReal physicalValue; + loader.fillParticle(&position,&physicalValue); + // put in tree + tree.insert(position, idxPart, physicalValue); + // get copy + particles[idxPart].position = position; + particles[idxPart].physicalValue = physicalValue; + particles[idxPart].potential = 0.0; + particles[idxPart].forces[0] = 0.0; + particles[idxPart].forces[1] = 0.0; + particles[idxPart].forces[2] = 0.0; + } // Run FMM @@ -105,50 +112,42 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { // Run direct computation const MatrixKernelClass MatrixKernel; Print("Direct..."); - for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){ - for(int idxOther = idxTarget + 1 ; idxOther < loader.getNumberOfParticles() ; ++idxOther){ - //kernels.directInteractionMutual(&particles[idxTarget], &particles[idxOther]); - const FReal wt = particles[idxTarget].getPhysicalValue(); - const FReal ws = particles[idxOther ].getPhysicalValue(); - const FReal one_over_r = MatrixKernel.evaluate(particles[idxTarget].getPosition(), - particles[idxOther].getPosition()); - // potential - particles[idxTarget].incPotential(one_over_r * ws); - particles[idxOther ].incPotential(one_over_r * wt); - // force - FPoint force(particles[idxOther].getPosition() - particles[idxTarget].getPosition()); - force *= ((ws*wt) * (one_over_r*one_over_r*one_over_r)); - particles[idxTarget].incForces( force.getX(), force.getY(), force.getZ()); - particles[idxOther ].incForces( -force.getX(), -force.getY(), -force.getZ()); - } - } + for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){ + for(int idxOther = idxTarget + 1 ; idxOther < loader.getNumberOfParticles() ; ++idxOther){ + FP2P::MutualParticles(particles[idxTarget].position.getX(), particles[idxTarget].position.getY(), + particles[idxTarget].position.getZ(),particles[idxTarget].physicalValue, + &particles[idxTarget].forces[0],&particles[idxTarget].forces[1], + &particles[idxTarget].forces[2],&particles[idxTarget].potential, + particles[idxOther].position.getX(), particles[idxOther].position.getY(), + particles[idxOther].position.getZ(),particles[idxOther].physicalValue, + &particles[idxOther].forces[0],&particles[idxOther].forces[1], + &particles[idxOther].forces[2],&particles[idxOther].potential); + } + } // Compare - Print("Compute Diff..."); - FMath::FAccurater potentialDiff; - FMath::FAccurater fx, fy, fz; - { // Check that each particle has been summed with all other - typename OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - - do{ - typename ContainerClass::BasicIterator leafIter(*octreeIterator.getCurrentListTargets()); - - while( leafIter.hasNotFinished() ){ - const ParticleClass& other = particles[leafIter.data().getIndex()]; - - potentialDiff.add(other.getPotential(),leafIter.data().getPotential()); - - fx.add(other.getForces().getX(),leafIter.data().getForces().getX()); - - fy.add(other.getForces().getY(),leafIter.data().getForces().getY()); - - fz.add(other.getForces().getZ(),leafIter.data().getForces().getZ()); - - leafIter.gotoNext(); - } - } while(octreeIterator.moveRight()); - } + Print("Compute Diff..."); + FMath::FAccurater potentialDiff; + FMath::FAccurater fx, fy, fz; + { // Check that each particle has been summed with all other + + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + const FVector<int>& indexes = leaf->getTargets()->getIndexes(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + const int indexPartOrig = indexes[idxPart]; + potentialDiff.add(particles[indexPartOrig].potential,potentials[idxPart]); + fx.add(particles[indexPartOrig].forces[0],forcesX[idxPart]); + fy.add(particles[indexPartOrig].forces[1],forcesY[idxPart]); + fz.add(particles[indexPartOrig].forces[2],forcesZ[idxPart]); + } + }); + } delete[] particles; @@ -201,33 +200,31 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { /** TestChebKernel */ void TestChebKernel(){ const unsigned int ORDER = 5; - const FReal epsilon = FReal(1e-5); - typedef IndexedParticle ParticleClass; - typedef FVector<ParticleClass> ContainerClass; - typedef FChebLeaf<ParticleClass,ContainerClass> LeafClass; + const FReal epsilon = FReal(1e-5); + typedef FP2PParticleContainerIndexed ContainerClass; + typedef FSimpleLeaf<ContainerClass> LeafClass; typedef FChebMatrixKernelR MatrixKernelClass; typedef FChebCell<ORDER> CellClass; - typedef FOctree<ParticleClass,CellClass,ContainerClass,LeafClass> OctreeClass; - typedef FChebKernel<ParticleClass,CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; - typedef FFmmAlgorithm<OctreeClass,ParticleClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; + typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; + typedef FChebKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; + typedef FFmmAlgorithm<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; // run test - RunTest<ParticleClass,CellClass,ContainerClass,KernelClass,MatrixKernelClass,LeafClass,OctreeClass,FmmClass>(epsilon); + RunTest<CellClass,ContainerClass,KernelClass,MatrixKernelClass,LeafClass,OctreeClass,FmmClass>(epsilon); } /** TestChebSymKernel */ void TestChebSymKernel(){ const unsigned int ORDER = 5; - const FReal epsilon = FReal(1e-5); - typedef IndexedParticle ParticleClass; - typedef FVector<ParticleClass> ContainerClass; - typedef FChebLeaf<ParticleClass,ContainerClass> LeafClass; + const FReal epsilon = FReal(1e-5); + typedef FP2PParticleContainerIndexed ContainerClass; + typedef FSimpleLeaf<ContainerClass> LeafClass; typedef FChebMatrixKernelR MatrixKernelClass; typedef FChebCell<ORDER> CellClass; - typedef FOctree<ParticleClass,CellClass,ContainerClass,LeafClass> OctreeClass; - typedef FChebSymKernel<ParticleClass,CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; - typedef FFmmAlgorithm<OctreeClass,ParticleClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; + typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; + typedef FChebSymKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; + typedef FFmmAlgorithm<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; // run test - RunTest<ParticleClass,CellClass,ContainerClass,KernelClass,MatrixKernelClass,LeafClass,OctreeClass,FmmClass>(epsilon); + RunTest<CellClass,ContainerClass,KernelClass,MatrixKernelClass,LeafClass,OctreeClass,FmmClass>(epsilon); } diff --git a/UTests/utestChebyshevDirectPeriodic.cpp b/UTests/utestChebyshevDirectPeriodic.cpp index 6e1c9d912..af11773ec 100755 --- a/UTests/utestChebyshevDirectPeriodic.cpp +++ b/UTests/utestChebyshevDirectPeriodic.cpp @@ -30,30 +30,19 @@ #include "FUTester.hpp" -#include "../Src/Kernels/Chebyshev/FChebParticle.hpp" #include "../Src/Kernels/Chebyshev/FChebLeaf.hpp" #include "../Src/Kernels/Chebyshev/FChebCell.hpp" #include "../Src/Kernels/Chebyshev/FChebMatrixKernel.hpp" #include "../Src/Kernels/Chebyshev/FChebKernel.hpp" #include "../Src/Kernels/Chebyshev/FChebSymKernel.hpp" +#include "../Src/Components/FSimpleLeaf.hpp" +#include "../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp" + /* In this test we compare the spherical fmm results and the direct results. */ -/** We need to know the position of the particle in the array */ -class IndexedParticle : public FChebParticle { - int index; -public: - IndexedParticle(): index(-1){} - - int getIndex() const{ - return index; - } - void setIndex( const int inIndex ){ - index = inIndex; - } -}; /** the test class * @@ -64,7 +53,7 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { // The tests! /////////////////////////////////////////////////////////// - template <class ParticleClass, class CellClass, class ContainerClass, class KernelClass, class MatrixKernelClass, + template <class CellClass, class ContainerClass, class KernelClass, class MatrixKernelClass, class LeafClass, class OctreeClass, class FmmClass> void RunTest(const FReal epsilon) { // Warning in make test the exec dir it Build/UTests @@ -75,19 +64,33 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { const int PeriodicDeep = 2; const int NbParticles = 1; - FRandomLoader<ParticleClass> loader(NbParticles); + FRandomLoader loader(NbParticles); Print("Number of particles:"); Print(loader.getNumberOfParticles()); // Create octree OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); - ParticleClass* const particles = new ParticleClass[loader.getNumberOfParticles()]; + + struct TestParticle{ + FPoint position; + FReal forces[3]; + FReal physicalValue; + FReal potential; + }; + TestParticle* const particles = new TestParticle[loader.getNumberOfParticles()]; for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - loader.fillParticle(particles[idxPart]); - particles[idxPart].setIndex( idxPart ); - particles[idxPart].setPhysicalValue(FReal(0.10)); - tree.insert(particles[idxPart]); + FPoint position; + loader.fillParticle(&position); + // put in tree + tree.insert(position, idxPart, 0.10); + // get copy + particles[idxPart].position = position; + particles[idxPart].physicalValue = 0.10; + particles[idxPart].potential = 0.0; + particles[idxPart].forces[0] = 0.0; + particles[idxPart].forces[1] = 0.0; + particles[idxPart].forces[2] = 0.0; } // Run FMM @@ -107,19 +110,14 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){ for(int idxOther = idxTarget + 1 ; idxOther < loader.getNumberOfParticles() ; ++idxOther){ - //kernels.directInteractionMutual(&particles[idxTarget], &particles[idxOther]); - const FReal wt = particles[idxTarget].getPhysicalValue(); - const FReal ws = particles[idxOther ].getPhysicalValue(); - const FReal one_over_r = MatrixKernel.evaluate(particles[idxTarget].getPosition(), - particles[idxOther].getPosition()); - // potential - particles[idxTarget].incPotential(one_over_r * ws); - particles[idxOther ].incPotential(one_over_r * wt); - // force - FPoint force(particles[idxOther].getPosition() - particles[idxTarget].getPosition()); - force *= ((ws*wt) * (one_over_r*one_over_r*one_over_r)); - particles[idxTarget].incForces( force.getX(), force.getY(), force.getZ()); - particles[idxOther ].incForces( -force.getX(), -force.getY(), -force.getZ()); + FP2P::MutualParticles(particles[idxTarget].position.getX(), particles[idxTarget].position.getY(), + particles[idxTarget].position.getZ(),particles[idxTarget].physicalValue, + &particles[idxTarget].forces[0],&particles[idxTarget].forces[1], + &particles[idxTarget].forces[2],&particles[idxTarget].potential, + particles[idxOther].position.getX(), particles[idxOther].position.getY(), + particles[idxOther].position.getZ(),particles[idxOther].physicalValue, + &particles[idxOther].forces[0],&particles[idxOther].forces[1], + &particles[idxOther].forces[2],&particles[idxOther].potential); } for(int idxX = min.getX() ; idxX <= max.getX() ; ++idxX){ for(int idxY = min.getY() ; idxY <= max.getY() ; ++idxY){ @@ -132,20 +130,16 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { loader.getBoxWidth() * FReal(idxZ)); for(int idxSource = 0 ; idxSource < NbParticles ; ++idxSource){ - ParticleClass source = particles[idxSource]; - source.incPosition(offset.getX(),offset.getY(),offset.getZ()); - - const FReal wt = particles[idxTarget].getPhysicalValue(); - const FReal ws = source.getPhysicalValue(); - const FReal one_over_r = MatrixKernel.evaluate(particles[idxTarget].getPosition(), - source.getPosition()); - // potential - particles[idxTarget].incPotential(one_over_r * ws); - source.incPotential(one_over_r * wt); - // force - FPoint force(source.getPosition() - particles[idxTarget].getPosition()); - force *= ((ws*wt) * (one_over_r*one_over_r*one_over_r)); - particles[idxTarget].incForces( force.getX(), force.getY(), force.getZ()); + TestParticle source = particles[idxSource]; + source.position += offset; + + FP2P::NonMutualParticles( + source.position.getX(), source.position.getY(), + source.position.getZ(),source.physicalValue, + particles[idxTarget].position.getX(), particles[idxTarget].position.getY(), + particles[idxTarget].position.getZ(),particles[idxTarget].physicalValue, + &particles[idxTarget].forces[0],&particles[idxTarget].forces[1], + &particles[idxTarget].forces[2],&particles[idxTarget].potential); } } } @@ -157,26 +151,23 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { FMath::FAccurater potentialDiff; FMath::FAccurater fx, fy, fz; { // Check that each particle has been summed with all other - typename OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - - do{ - typename ContainerClass::BasicIterator leafIter(*octreeIterator.getCurrentListTargets()); - - while( leafIter.hasNotFinished() ){ - const ParticleClass& other = particles[leafIter.data().getIndex()]; - - potentialDiff.add(other.getPotential(),leafIter.data().getPotential()); - - fx.add(other.getForces().getX(),leafIter.data().getForces().getX()); - - fy.add(other.getForces().getY(),leafIter.data().getForces().getY()); - - fz.add(other.getForces().getZ(),leafIter.data().getForces().getZ()); - leafIter.gotoNext(); + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + const FVector<int>& indexes = leaf->getTargets()->getIndexes(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + const int indexPartOrig = indexes[idxPart]; + potentialDiff.add(particles[indexPartOrig].potential,potentials[idxPart]); + fx.add(particles[indexPartOrig].forces[0],forcesX[idxPart]); + fy.add(particles[indexPartOrig].forces[1],forcesY[idxPart]); + fz.add(particles[indexPartOrig].forces[2],forcesZ[idxPart]); } - } while(octreeIterator.moveRight()); + }); } delete[] particles; @@ -231,33 +222,31 @@ class TestChebyshevDirect : public FUTester<TestChebyshevDirect> { /** TestChebKernel */ void TestChebKernel(){ const unsigned int ORDER = 5; - const FReal epsilon = FReal(1e-5); - typedef IndexedParticle ParticleClass; - typedef FVector<ParticleClass> ContainerClass; - typedef FChebLeaf<ParticleClass,ContainerClass> LeafClass; + const FReal epsilon = FReal(1e-5); + typedef FP2PParticleContainerIndexed ContainerClass; + typedef FSimpleLeaf<ContainerClass> LeafClass; typedef FChebMatrixKernelR MatrixKernelClass; typedef FChebCell<ORDER> CellClass; - typedef FOctree<ParticleClass,CellClass,ContainerClass,LeafClass> OctreeClass; - typedef FChebKernel<ParticleClass,CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; - typedef FFmmAlgorithmPeriodic<OctreeClass,ParticleClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; + typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; + typedef FChebKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; + typedef FFmmAlgorithmPeriodic<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; // run test - RunTest<ParticleClass,CellClass,ContainerClass,KernelClass,MatrixKernelClass,LeafClass,OctreeClass,FmmClass>(epsilon); + RunTest<CellClass,ContainerClass,KernelClass,MatrixKernelClass,LeafClass,OctreeClass,FmmClass>(epsilon); } /** TestChebSymKernel */ void TestChebSymKernel(){ const unsigned int ORDER = 5; - const FReal epsilon = FReal(1e-5); - typedef IndexedParticle ParticleClass; - typedef FVector<ParticleClass> ContainerClass; - typedef FChebLeaf<ParticleClass,ContainerClass> LeafClass; + const FReal epsilon = FReal(1e-5); + typedef FP2PParticleContainerIndexed ContainerClass; + typedef FSimpleLeaf<ContainerClass> LeafClass; typedef FChebMatrixKernelR MatrixKernelClass; typedef FChebCell<ORDER> CellClass; - typedef FOctree<ParticleClass,CellClass,ContainerClass,LeafClass> OctreeClass; - typedef FChebSymKernel<ParticleClass,CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; - typedef FFmmAlgorithmPeriodic<OctreeClass,ParticleClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; + typedef FOctree<CellClass,ContainerClass,LeafClass> OctreeClass; + typedef FChebSymKernel<CellClass,ContainerClass,MatrixKernelClass,ORDER> KernelClass; + typedef FFmmAlgorithmPeriodic<OctreeClass,CellClass,ContainerClass,KernelClass,LeafClass> FmmClass; // run test - RunTest<ParticleClass,CellClass,ContainerClass,KernelClass,MatrixKernelClass,LeafClass,OctreeClass,FmmClass>(epsilon); + RunTest<CellClass,ContainerClass,KernelClass,MatrixKernelClass,LeafClass,OctreeClass,FmmClass>(epsilon); } diff --git a/UTests/utestOctree.cpp b/UTests/utestOctree.cpp index 5950f45bf..c9c259fe2 100755 --- a/UTests/utestOctree.cpp +++ b/UTests/utestOctree.cpp @@ -22,7 +22,7 @@ #include "../Src/Utils/FAssertable.hpp" #include "../Src/Utils/FPoint.hpp" -#include "../Src/Components/FBasicParticle.hpp" +#include "../Src/Components/FBasicParticleContainer.hpp" #include "../Src/Components/FBasicCell.hpp" #include "../Src/Utils/FTic.hpp" @@ -36,12 +36,11 @@ /** this class test the octree container */ class TestOctree : public FUTester<TestOctree> { - typedef FBasicParticle ParticleClass; typedef FBasicCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FBasicParticleContainer<0> ContainerClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree<CellClass, ContainerClass , LeafClass > OctreeClass; // test size void TestAll(){ @@ -64,14 +63,13 @@ class TestOctree : public FUTester<TestOctree> { OctreeClass tree(idxHeight, idxSub, BoxWidth, FPoint(BoxCenter,BoxCenter,BoxCenter)); // fill the tree - ParticleClass particleToFill; for(int idxX = 0 ; idxX < NbSmallBoxesPerSide ; ++idxX){ for(int idxY = 0 ; idxY < NbSmallBoxesPerSide ; ++idxY){ for(int idxZ = 0 ; idxZ < NbSmallBoxesPerSide ; ++idxZ){ - particleToFill.setPosition(FReal(idxX)*SmallBoxWidth + SmallBoxWidthDiv2, + const FPoint pos(FReal(idxX)*SmallBoxWidth + SmallBoxWidthDiv2, FReal(idxY)*SmallBoxWidth + SmallBoxWidthDiv2, FReal(idxZ)*SmallBoxWidth + SmallBoxWidthDiv2); - tree.insert(particleToFill); + tree.insert(pos); } } } diff --git a/UTests/utestRotationDirect.cpp b/UTests/utestRotationDirect.cpp index b35bf64b2..4773d15a9 100755 --- a/UTests/utestRotationDirect.cpp +++ b/UTests/utestRotationDirect.cpp @@ -20,7 +20,7 @@ #include "../Src/Containers/FVector.hpp" #include "../Src/Kernels/Rotation/FRotationCell.hpp" -#include "../Src/Kernels/Rotation/FRotationParticle.hpp" +#include "../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp" #include "../Src/Components/FSimpleLeaf.hpp" #include "../Src/Kernels/Rotation/FRotationKernel.hpp" @@ -33,30 +33,13 @@ #include "FUTester.hpp" -/* - In this test we compare the spherical fmm results and the direct results. - */ - -/** We need to know the position of the particle in the array */ -class IndexedParticle : public FRotationParticle { - int index; -public: - IndexedParticle(): index(-1){} - - int getIndex() const{ - return index; - } - void setIndex( const int inIndex ){ - index = inIndex; - } -}; /** the test class * */ class TestRotationDirect : public FUTester<TestRotationDirect> { /** The test method to factorize all the test based on different kernels */ - template <class ParticleClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass, + template <class CellClass, class ContainerClass, class KernelClass, class LeafClass, class OctreeClass, class FmmClass> void RunTest(){ // Warning in make test the exec dir it Build/UTests @@ -64,7 +47,7 @@ class TestRotationDirect : public FUTester<TestRotationDirect> { const char* const filename = (sizeof(FReal) == sizeof(float))? "../../Data/utestDirect.bin.fma.single": "../../Data/utestDirect.bin.fma.double"; - FFmaBinLoader<ParticleClass> loader(filename); + FFmaBinLoader loader(filename); if(!loader.isOpen()){ Print("Cannot open particles file."); uassert(false); @@ -76,13 +59,31 @@ class TestRotationDirect : public FUTester<TestRotationDirect> { const int NbLevels = 4; const int SizeSubLevels = 2; + + struct TestParticle{ + FPoint position; + FReal forces[3]; + FReal physicalValue; + FReal potential; + }; + + TestParticle* const particles = new TestParticle[loader.getNumberOfParticles()]; + // Create octree OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); - ParticleClass* const particles = new ParticleClass[loader.getNumberOfParticles()]; for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - loader.fillParticle(particles[idxPart]); - particles[idxPart].setIndex( idxPart ); - tree.insert(particles[idxPart]); + FPoint position; + FReal physicalValue; + loader.fillParticle(&position,&physicalValue); + // put in tree + tree.insert(position, idxPart, physicalValue); + // get copy + particles[idxPart].position = position; + particles[idxPart].physicalValue = physicalValue; + particles[idxPart].potential = 0.0; + particles[idxPart].forces[0] = 0.0; + particles[idxPart].forces[1] = 0.0; + particles[idxPart].forces[2] = 0.0; } @@ -97,7 +98,14 @@ class TestRotationDirect : public FUTester<TestRotationDirect> { Print("Direct..."); for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){ for(int idxOther = idxTarget + 1 ; idxOther < loader.getNumberOfParticles() ; ++idxOther){ - kernels.particlesMutualInteraction(&particles[idxTarget], &particles[idxOther]); + FP2P::MutualParticles(particles[idxTarget].position.getX(), particles[idxTarget].position.getY(), + particles[idxTarget].position.getZ(),particles[idxTarget].physicalValue, + &particles[idxTarget].forces[0],&particles[idxTarget].forces[1], + &particles[idxTarget].forces[2],&particles[idxTarget].potential, + particles[idxOther].position.getX(), particles[idxOther].position.getY(), + particles[idxOther].position.getZ(),particles[idxOther].physicalValue, + &particles[idxOther].forces[0],&particles[idxOther].forces[1], + &particles[idxOther].forces[2],&particles[idxOther].potential); } } @@ -106,26 +114,23 @@ class TestRotationDirect : public FUTester<TestRotationDirect> { FMath::FAccurater potentialDiff; FMath::FAccurater fx, fy, fz; { // Check that each particle has been summed with all other - typename OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - - do{ - typename ContainerClass::BasicIterator leafIter(*octreeIterator.getCurrentListTargets()); - - while( leafIter.hasNotFinished() ){ - const ParticleClass& other = particles[leafIter.data().getIndex()]; - - potentialDiff.add(other.getPotential(),leafIter.data().getPotential()); - - fx.add(other.getForces().getX(),leafIter.data().getForces().getX()); - - fy.add(other.getForces().getY(),leafIter.data().getForces().getY()); - - fz.add(other.getForces().getZ(),leafIter.data().getForces().getZ()); - leafIter.gotoNext(); + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + const FVector<int>& indexes = leaf->getTargets()->getIndexes(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + const int indexPartOrig = indexes[idxPart]; + potentialDiff.add(particles[indexPartOrig].potential,potentials[idxPart]); + fx.add(particles[indexPartOrig].forces[0],forcesX[idxPart]); + fy.add(particles[indexPartOrig].forces[1],forcesY[idxPart]); + fz.add(particles[indexPartOrig].forces[2],forcesZ[idxPart]); } - } while(octreeIterator.moveRight()); + }); } delete[] particles; @@ -173,19 +178,17 @@ class TestRotationDirect : public FUTester<TestRotationDirect> { /** Rotation */ void TestRotation(){ - typedef IndexedParticle ParticleClass; - typedef FRotationCell<P> CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FRotationCell<P> CellClass; + typedef FP2PParticleContainerIndexed ContainerClass; - typedef FRotationKernel<ParticleClass, CellClass, ContainerClass, P > KernelClass; + typedef FRotationKernel<CellClass, ContainerClass, P > KernelClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSimpleLeaf<ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - RunTest<ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass, - OctreeClass, FmmClass>(); + RunTest<CellClass, ContainerClass, KernelClass, LeafClass, OctreeClass, FmmClass>(); } /////////////////////////////////////////////////////////// diff --git a/UTests/utestRotationDirectPeriodic.cpp b/UTests/utestRotationDirectPeriodic.cpp index 30ab1a604..d230fb42d 100755 --- a/UTests/utestRotationDirectPeriodic.cpp +++ b/UTests/utestRotationDirectPeriodic.cpp @@ -18,7 +18,7 @@ #include "../Src/Kernels/Rotation/FRotationCell.hpp" #include "../Src/Kernels/Rotation/FRotationKernel.hpp" -#include "../Src/Kernels/Rotation/FRotationParticle.hpp" +#include "../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp" #include "../Src/Components/FSimpleLeaf.hpp" #include "../Src/Core/FFmmAlgorithmPeriodic.hpp" @@ -28,54 +28,49 @@ #include "../Src/Components/FTestCell.hpp" #include "../Src/Components/FTestKernels.hpp" -#include "../Src/Components/FTestParticle.hpp" - -/* - In this test we compare the fmm results and the direct results. - */ -class IndexedParticle : public FRotationParticle { - int index; -public: - IndexedParticle(): index(-1){} - - int getIndex() const{ - return index; - } - void setIndex( const int inIndex ){ - index = inIndex; - } -}; /** The class to run the test */ class TestRotationDirectPeriodic : public FUTester<TestRotationDirectPeriodic> { /** Here we test only the P2P */ void TestPeriodicFmm(){ static const int P = 9; - typedef IndexedParticle ParticleClass; typedef FRotationCell<P> CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainerIndexed ContainerClass; - typedef FRotationKernel<ParticleClass, CellClass, ContainerClass, P > KernelClass; + typedef FRotationKernel< CellClass, ContainerClass, P > KernelClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FFmmAlgorithmPeriodic<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithmPeriodic<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; // Parameters const int NbLevels = 4; const int SizeSubLevels = 2; const int PeriodicDeep = -1; const int NbParticles = 100; - ParticleClass* const particles = new ParticleClass[NbParticles]; - FRandomLoader<ParticleClass> loader(NbParticles); + FRandomLoader loader(NbParticles); OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); - for( int idxPart = 0 ; idxPart < NbParticles ; ++idxPart ){ - loader.fillParticle(particles[idxPart]); - particles[idxPart].setIndex(idxPart); - particles[idxPart].setPhysicalValue(FReal(0.80)); - tree.insert(particles[idxPart]); + struct TestParticle{ + FPoint position; + FReal forces[3]; + FReal physicalValue; + FReal potential; + }; + TestParticle* const particles = new TestParticle[loader.getNumberOfParticles()]; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint position; + loader.fillParticle(&position); + // put in tree + tree.insert(position, idxPart, 0.10); + // get copy + particles[idxPart].position = position; + particles[idxPart].physicalValue = 0.10; + particles[idxPart].potential = 0.0; + particles[idxPart].forces[0] = 0.0; + particles[idxPart].forces[1] = 0.0; + particles[idxPart].forces[2] = 0.0; } // Run FMM @@ -90,23 +85,38 @@ class TestRotationDirectPeriodic : public FUTester<TestRotationDirectPeriodic> { FTreeCoordinate min, max; algo.repetitionsIntervals(&min, &max); - for(int idxTarget = 0 ; idxTarget < NbParticles ; ++idxTarget){ - for(int idxSource = idxTarget + 1 ; idxSource < NbParticles ; ++idxSource){ - kernels.particlesMutualInteraction(&particles[idxTarget], &particles[idxSource]); + for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){ + for(int idxOther = idxTarget + 1 ; idxOther < loader.getNumberOfParticles() ; ++idxOther){ + FP2P::MutualParticles(particles[idxTarget].position.getX(), particles[idxTarget].position.getY(), + particles[idxTarget].position.getZ(),particles[idxTarget].physicalValue, + &particles[idxTarget].forces[0],&particles[idxTarget].forces[1], + &particles[idxTarget].forces[2],&particles[idxTarget].potential, + particles[idxOther].position.getX(), particles[idxOther].position.getY(), + particles[idxOther].position.getZ(),particles[idxOther].physicalValue, + &particles[idxOther].forces[0],&particles[idxOther].forces[1], + &particles[idxOther].forces[2],&particles[idxOther].potential); } for(int idxX = min.getX() ; idxX <= max.getX() ; ++idxX){ for(int idxY = min.getY() ; idxY <= max.getY() ; ++idxY){ for(int idxZ = min.getZ() ; idxZ <= max.getZ() ; ++idxZ){ - if(idxX == 0 && idxY == 0 && idxZ == 0) continue; + if(idxX ==0 && idxY == 0 && idxZ == 0) continue; + // next lines for test const FPoint offset(loader.getBoxWidth() * FReal(idxX), loader.getBoxWidth() * FReal(idxY), loader.getBoxWidth() * FReal(idxZ)); for(int idxSource = 0 ; idxSource < NbParticles ; ++idxSource){ - ParticleClass source = particles[idxSource]; - source.incPosition(offset.getX(),offset.getY(),offset.getZ()); - kernels.particlesInteraction(&particles[idxTarget], source); + TestParticle source = particles[idxSource]; + source.position += offset; + + FP2P::NonMutualParticles( + source.position.getX(), source.position.getY(), + source.position.getZ(),source.physicalValue, + particles[idxTarget].position.getX(), particles[idxTarget].position.getY(), + particles[idxTarget].position.getZ(),particles[idxTarget].physicalValue, + &particles[idxTarget].forces[0],&particles[idxTarget].forces[1], + &particles[idxTarget].forces[2],&particles[idxTarget].potential); } } } @@ -118,35 +128,23 @@ class TestRotationDirectPeriodic : public FUTester<TestRotationDirectPeriodic> { FMath::FAccurater potentialDiff; FMath::FAccurater fx, fy, fz; { // Check that each particle has been summed with all other - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - - do{ - ContainerClass::BasicIterator leafIter(*octreeIterator.getCurrentListTargets()); - - while( leafIter.hasNotFinished() ){ - const ParticleClass& other = particles[leafIter.data().getIndex()]; - - /*printf("Tree x %e y %e z %e physical %e potential %e fx %e fy %e fz %e\n", - leafIter.data().getPosition().getX(),leafIter.data().getPosition().getY(),leafIter.data().getPosition().getZ(), - leafIter.data().getPhysicalValue(),leafIter.data().getPotential(), - leafIter.data().getForces().getX(),leafIter.data().getForces().getY(),leafIter.data().getForces().getZ());// todo delete - printf("Direct x %e y %e z %e physical %e potential %e fx %e fy %e fz %e\n", - other.getPosition().getX(),other.getPosition().getY(),other.getPosition().getZ(), - other.getPhysicalValue(),other.getPotential(), - other.getForces().getX(),other.getForces().getY(),other.getForces().getZ());//*/ - - potentialDiff.add(other.getPotential(),leafIter.data().getPotential()); - - fx.add(other.getForces().getX(),leafIter.data().getForces().getX()); - - fy.add(other.getForces().getY(),leafIter.data().getForces().getY()); - - fz.add(other.getForces().getZ(),leafIter.data().getForces().getZ()); - leafIter.gotoNext(); + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + const FVector<int>& indexes = leaf->getTargets()->getIndexes(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + const int indexPartOrig = indexes[idxPart]; + potentialDiff.add(particles[indexPartOrig].potential,potentials[idxPart]); + fx.add(particles[indexPartOrig].forces[0],forcesX[idxPart]); + fy.add(particles[indexPartOrig].forces[1],forcesY[idxPart]); + fz.add(particles[indexPartOrig].forces[2],forcesZ[idxPart]); } - } while(octreeIterator.moveRight()); + }); } Print("Potential diff is = "); diff --git a/UTests/utestSphericalDirect.cpp b/UTests/utestSphericalDirect.cpp index b1d49e705..b8b4d5f9f 100755 --- a/UTests/utestSphericalDirect.cpp +++ b/UTests/utestSphericalDirect.cpp @@ -20,7 +20,7 @@ #include "../Src/Containers/FVector.hpp" #include "../Src/Kernels/Spherical/FSphericalCell.hpp" -#include "../Src/Kernels/Spherical/FSphericalParticle.hpp" +#include "../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp" #include "../Src/Components/FSimpleLeaf.hpp" #include "../Src/Kernels/Spherical/FSphericalKernel.hpp" @@ -40,26 +40,12 @@ In this test we compare the spherical fmm results and the direct results. */ -/** We need to know the position of the particle in the array */ -class IndexedParticle : public FSphericalParticle { - int index; -public: - IndexedParticle(): index(-1){} - - int getIndex() const{ - return index; - } - void setIndex( const int inIndex ){ - index = inIndex; - } -}; - /** the test class * */ class TestSphericalDirect : public FUTester<TestSphericalDirect> { /** The test method to factorize all the test based on different kernels */ - template <class ParticleClass, class CellClass, class ContainerClass, class KernelClass, class LeafClass, + template < class CellClass, class ContainerClass, class KernelClass, class LeafClass, class OctreeClass, class FmmClass> void RunTest(const bool isBlasKernel){ // Warning in make test the exec dir it Build/UTests @@ -67,7 +53,7 @@ class TestSphericalDirect : public FUTester<TestSphericalDirect> { const char* const filename = (sizeof(FReal) == sizeof(float))? "../../Data/utestDirect.bin.fma.single": "../../Data/utestDirect.bin.fma.double"; - FFmaBinLoader<ParticleClass> loader(filename); + FFmaBinLoader loader(filename); if(!loader.isOpen()){ Print("Cannot open particles file."); uassert(false); @@ -81,13 +67,31 @@ class TestSphericalDirect : public FUTester<TestSphericalDirect> { const int DevP = 9; FSphericalCell::Init(DevP, isBlasKernel); + // Create octree + struct TestParticle{ + FPoint position; + FReal forces[3]; + FReal physicalValue; + FReal potential; + }; + + TestParticle* const particles = new TestParticle[loader.getNumberOfParticles()]; + // Create octree OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); - ParticleClass* const particles = new ParticleClass[loader.getNumberOfParticles()]; for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - loader.fillParticle(particles[idxPart]); - particles[idxPart].setIndex( idxPart ); - tree.insert(particles[idxPart]); + FPoint position; + FReal physicalValue; + loader.fillParticle(&position,&physicalValue); + // put in tree + tree.insert(position, idxPart, physicalValue); + // get copy + particles[idxPart].position = position; + particles[idxPart].physicalValue = physicalValue; + particles[idxPart].potential = 0.0; + particles[idxPart].forces[0] = 0.0; + particles[idxPart].forces[1] = 0.0; + particles[idxPart].forces[2] = 0.0; } @@ -102,7 +106,14 @@ class TestSphericalDirect : public FUTester<TestSphericalDirect> { Print("Direct..."); for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){ for(int idxOther = idxTarget + 1 ; idxOther < loader.getNumberOfParticles() ; ++idxOther){ - kernels.directInteractionMutual(&particles[idxTarget], &particles[idxOther]); + FP2P::MutualParticles(particles[idxTarget].position.getX(), particles[idxTarget].position.getY(), + particles[idxTarget].position.getZ(),particles[idxTarget].physicalValue, + &particles[idxTarget].forces[0],&particles[idxTarget].forces[1], + &particles[idxTarget].forces[2],&particles[idxTarget].potential, + particles[idxOther].position.getX(), particles[idxOther].position.getY(), + particles[idxOther].position.getZ(),particles[idxOther].physicalValue, + &particles[idxOther].forces[0],&particles[idxOther].forces[1], + &particles[idxOther].forces[2],&particles[idxOther].potential); } } @@ -111,26 +122,23 @@ class TestSphericalDirect : public FUTester<TestSphericalDirect> { FMath::FAccurater potentialDiff; FMath::FAccurater fx, fy, fz; { // Check that each particle has been summed with all other - typename OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - - do{ - typename ContainerClass::BasicIterator leafIter(*octreeIterator.getCurrentListTargets()); - - while( leafIter.hasNotFinished() ){ - const ParticleClass& other = particles[leafIter.data().getIndex()]; - - potentialDiff.add(other.getPotential(),leafIter.data().getPotential()); - - fx.add(other.getForces().getX(),leafIter.data().getForces().getX()); - - fy.add(other.getForces().getY(),leafIter.data().getForces().getY()); - - fz.add(other.getForces().getZ(),leafIter.data().getForces().getZ()); - leafIter.gotoNext(); + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + const FVector<int>& indexes = leaf->getTargets()->getIndexes(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + const int indexPartOrig = indexes[idxPart]; + potentialDiff.add(particles[indexPartOrig].potential,potentials[idxPart]); + fx.add(particles[indexPartOrig].forces[0],forcesX[idxPart]); + fy.add(particles[indexPartOrig].forces[1],forcesY[idxPart]); + fz.add(particles[indexPartOrig].forces[2],forcesZ[idxPart]); } - } while(octreeIterator.moveRight()); + }); } delete[] particles; @@ -176,70 +184,66 @@ class TestSphericalDirect : public FUTester<TestSphericalDirect> { /** Classic */ void TestSpherical(){ - typedef IndexedParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainerIndexed ContainerClass; - typedef FSphericalKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSphericalKernel< CellClass, ContainerClass > KernelClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - RunTest<ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass, + RunTest< CellClass, ContainerClass, KernelClass, LeafClass, OctreeClass, FmmClass>(false); } /** Rotation */ void TestRotation(){ - typedef IndexedParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainerIndexed ContainerClass; - typedef FSphericalRotationKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSphericalRotationKernel< CellClass, ContainerClass > KernelClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - RunTest<ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass, + RunTest< CellClass, ContainerClass, KernelClass, LeafClass, OctreeClass, FmmClass>(false); } #ifdef SCALFMM_USE_BLAS /** Blas */ void TestSphericalBlas(){ - typedef IndexedParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainerIndexed ContainerClass; - typedef FSphericalBlasKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSphericalBlasKernel< CellClass, ContainerClass > KernelClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - RunTest<ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass, + RunTest< CellClass, ContainerClass, KernelClass, LeafClass, OctreeClass, FmmClass>(true); } /** Block blas */ void TestSphericalBlockBlas(){ - typedef IndexedParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainerIndexed ContainerClass; - typedef FSphericalBlockBlasKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSphericalBlockBlasKernel< CellClass, ContainerClass > KernelClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; - RunTest<ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass, + RunTest< CellClass, ContainerClass, KernelClass, LeafClass, OctreeClass, FmmClass>(true); } #endif diff --git a/UTests/utestSphericalDirectPeriodic.cpp b/UTests/utestSphericalDirectPeriodic.cpp index be0af8912..f9c9a6c36 100755 --- a/UTests/utestSphericalDirectPeriodic.cpp +++ b/UTests/utestSphericalDirectPeriodic.cpp @@ -18,7 +18,7 @@ #include "../Src/Kernels/Spherical/FSphericalCell.hpp" #include "../Src/Kernels/Spherical/FSphericalKernel.hpp" -#include "../Src/Kernels/Spherical/FSphericalParticle.hpp" +#include "../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp" #include "../Src/Components/FSimpleLeaf.hpp" #include "../Src/Core/FFmmAlgorithmPeriodic.hpp" @@ -28,38 +28,22 @@ #include "../Src/Components/FTestCell.hpp" #include "../Src/Components/FTestKernels.hpp" -#include "../Src/Components/FTestParticle.hpp" - -/* - In this test we compare the fmm results and the direct results. - */ -class IndexedParticle : public FSphericalParticle { - int index; -public: - IndexedParticle(): index(-1){} - - int getIndex() const{ - return index; - } - void setIndex( const int inIndex ){ - index = inIndex; - } -}; + + /** The class to run the test */ class TestSphericalDirectPeriodic : public FUTester<TestSphericalDirectPeriodic> { /** Here we test only the P2P */ void TestPeriodicFmm(){ - typedef IndexedParticle ParticleClass; typedef FSphericalCell CellClass; - typedef FVector<ParticleClass> ContainerClass; + typedef FP2PParticleContainerIndexed ContainerClass; - typedef FSphericalKernel<ParticleClass, CellClass, ContainerClass > KernelClass; + typedef FSphericalKernel<CellClass, ContainerClass > KernelClass; - typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; - typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; + typedef FSimpleLeaf< ContainerClass > LeafClass; + typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; - typedef FFmmAlgorithmPeriodic<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; + typedef FFmmAlgorithmPeriodic<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; // Parameters const int NbLevels = 3; @@ -67,17 +51,30 @@ class TestSphericalDirectPeriodic : public FUTester<TestSphericalDirectPeriodic> const int PeriodicDeep = 3; const int DevP = 9; const int NbParticles = 1; - ParticleClass* const particles = new ParticleClass[NbParticles]; FSphericalCell::Init(DevP); - FRandomLoader<ParticleClass> loader(NbParticles); + FRandomLoader loader(NbParticles); OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); - for( int idxPart = 0 ; idxPart < NbParticles ; ++idxPart ){ - loader.fillParticle(particles[idxPart]); - particles[idxPart].setIndex(idxPart); - particles[idxPart].setPhysicalValue(FReal(0.10)); - tree.insert(particles[idxPart]); + struct TestParticle{ + FPoint position; + FReal forces[3]; + FReal physicalValue; + FReal potential; + }; + TestParticle* const particles = new TestParticle[loader.getNumberOfParticles()]; + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint position; + loader.fillParticle(&position); + // put in tree + tree.insert(position, idxPart, 0.10); + // get copy + particles[idxPart].position = position; + particles[idxPart].physicalValue = 0.10; + particles[idxPart].potential = 0.0; + particles[idxPart].forces[0] = 0.0; + particles[idxPart].forces[1] = 0.0; + particles[idxPart].forces[2] = 0.0; } // Run FMM @@ -92,23 +89,38 @@ class TestSphericalDirectPeriodic : public FUTester<TestSphericalDirectPeriodic> FTreeCoordinate min, max; algo.repetitionsIntervals(&min, &max); - for(int idxTarget = 0 ; idxTarget < NbParticles ; ++idxTarget){ - for(int idxSource = idxTarget + 1 ; idxSource < NbParticles ; ++idxSource){ - kernels.directInteractionMutual(&particles[idxTarget], &particles[idxSource]); + for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){ + for(int idxOther = idxTarget + 1 ; idxOther < loader.getNumberOfParticles() ; ++idxOther){ + FP2P::MutualParticles(particles[idxTarget].position.getX(), particles[idxTarget].position.getY(), + particles[idxTarget].position.getZ(),particles[idxTarget].physicalValue, + &particles[idxTarget].forces[0],&particles[idxTarget].forces[1], + &particles[idxTarget].forces[2],&particles[idxTarget].potential, + particles[idxOther].position.getX(), particles[idxOther].position.getY(), + particles[idxOther].position.getZ(),particles[idxOther].physicalValue, + &particles[idxOther].forces[0],&particles[idxOther].forces[1], + &particles[idxOther].forces[2],&particles[idxOther].potential); } for(int idxX = min.getX() ; idxX <= max.getX() ; ++idxX){ for(int idxY = min.getY() ; idxY <= max.getY() ; ++idxY){ for(int idxZ = min.getZ() ; idxZ <= max.getZ() ; ++idxZ){ - if(idxX == 0 && idxY == 0 && idxZ == 0) continue; + if(idxX ==0 && idxY == 0 && idxZ == 0) continue; + // next lines for test const FPoint offset(loader.getBoxWidth() * FReal(idxX), loader.getBoxWidth() * FReal(idxY), loader.getBoxWidth() * FReal(idxZ)); for(int idxSource = 0 ; idxSource < NbParticles ; ++idxSource){ - ParticleClass source = particles[idxSource]; - source.incPosition(offset.getX(),offset.getY(),offset.getZ()); - kernels.directInteraction(&particles[idxTarget], source); + TestParticle source = particles[idxSource]; + source.position += offset; + + FP2P::NonMutualParticles( + source.position.getX(), source.position.getY(), + source.position.getZ(),source.physicalValue, + particles[idxTarget].position.getX(), particles[idxTarget].position.getY(), + particles[idxTarget].position.getZ(),particles[idxTarget].physicalValue, + &particles[idxTarget].forces[0],&particles[idxTarget].forces[1], + &particles[idxTarget].forces[2],&particles[idxTarget].potential); } } } @@ -120,26 +132,23 @@ class TestSphericalDirectPeriodic : public FUTester<TestSphericalDirectPeriodic> FMath::FAccurater potentialDiff; FMath::FAccurater fx, fy, fz; { // Check that each particle has been summed with all other - OctreeClass::Iterator octreeIterator(&tree); - octreeIterator.gotoBottomLeft(); - - do{ - ContainerClass::BasicIterator leafIter(*octreeIterator.getCurrentListTargets()); - - while( leafIter.hasNotFinished() ){ - const ParticleClass& other = particles[leafIter.data().getIndex()]; - - potentialDiff.add(other.getPotential(),leafIter.data().getPotential()); - - fx.add(other.getForces().getX(),leafIter.data().getForces().getX()); - - fy.add(other.getForces().getY(),leafIter.data().getForces().getY()); - - fz.add(other.getForces().getZ(),leafIter.data().getForces().getZ()); - leafIter.gotoNext(); + tree.forEachLeaf([&](LeafClass* leaf){ + const FReal*const potentials = leaf->getTargets()->getPotentials(); + const FReal*const forcesX = leaf->getTargets()->getForcesX(); + const FReal*const forcesY = leaf->getTargets()->getForcesY(); + const FReal*const forcesZ = leaf->getTargets()->getForcesZ(); + const int nbParticlesInLeaf = leaf->getTargets()->getNbParticles(); + const FVector<int>& indexes = leaf->getTargets()->getIndexes(); + + for(int idxPart = 0 ; idxPart < nbParticlesInLeaf ; ++idxPart){ + const int indexPartOrig = indexes[idxPart]; + potentialDiff.add(particles[indexPartOrig].potential,potentials[idxPart]); + fx.add(particles[indexPartOrig].forces[0],forcesX[idxPart]); + fy.add(particles[indexPartOrig].forces[1],forcesY[idxPart]); + fz.add(particles[indexPartOrig].forces[2],forcesZ[idxPart]); } - } while(octreeIterator.moveRight()); + }); } Print("Potential diff is = "); diff --git a/UTests/utestSphericalWithPrevious.cpp b/UTests/utestSphericalWithPrevious.cpp index 03ca57fd8..481828d4e 100755 --- a/UTests/utestSphericalWithPrevious.cpp +++ b/UTests/utestSphericalWithPrevious.cpp @@ -18,7 +18,6 @@ #include "../Src/Kernels/Spherical/FSphericalCell.hpp" #include "../Src/Kernels/Spherical/FSphericalKernel.hpp" -#include "../Src/Kernels/Spherical/FSphericalParticle.hpp" #include "../Src/Components/FSimpleLeaf.hpp" #include "../Src/Files/FFmaBinLoader.hpp" @@ -27,23 +26,22 @@ #include "../Src/Core/FFmmAlgorithm.hpp" #include "FUTester.hpp" - +#include "../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp" /** * This test compare a previous FMM result with a previous simulation result. */ -typedef FSphericalParticle ParticleClass; typedef FSphericalCell CellClass; -typedef FVector<ParticleClass> ContainerClass; +typedef FP2PParticleContainerIndexed ContainerClass; -typedef FSphericalKernel<ParticleClass, CellClass, ContainerClass > KernelClass; +typedef FSphericalKernel< CellClass, ContainerClass > KernelClass; -typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass; -typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass; +typedef FSimpleLeaf< ContainerClass > LeafClass; +typedef FOctree< CellClass, ContainerClass , LeafClass > OctreeClass; -typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; +typedef FFmmAlgorithm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass; /** To check if a value is correct */ bool IsSimilar(const FReal good, const FReal other){ @@ -68,7 +66,7 @@ class TestSphericalWithPrevious : public FUTester<TestSphericalWithPrevious> { const int DevP = 9; // Load the particles file - FFmaBinLoader<ParticleClass> loader(ParticleFile); + FFmaBinLoader loader(ParticleFile); if(!loader.isOpen()){ Print("Cannot open particles file."); uassert(false); @@ -78,7 +76,13 @@ class TestSphericalWithPrevious : public FUTester<TestSphericalWithPrevious> { // Create octree FSphericalCell::Init(DevP); OctreeClass testTree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); - loader.fillTree(testTree); + for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ + FPoint position; + FReal physicalValue = 0.0; + loader.fillParticle(&position,&physicalValue); + // put in tree + testTree.insert(position, idxPart, physicalValue); + } // Run simulation KernelClass kernels(DevP, NbLevels, loader.getBoxWidth(), loader.getCenterOfBox()); @@ -86,11 +90,11 @@ class TestSphericalWithPrevious : public FUTester<TestSphericalWithPrevious> { algo.execute(); // If needed save the result - // FTreeIO::Save<OctreeClass, CellClass, ParticleClass, ContainerClass >(DataFile, testTree); + // FTreeIO::Save<OctreeClass, CellClass, LeafClass, ContainerClass >(DataFile, testTree); // Load previous result OctreeClass goodTree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox()); - FTreeIO::Load<OctreeClass, CellClass, ParticleClass, ContainerClass >(DataFile, goodTree); + FTreeIO::Load<OctreeClass, CellClass, LeafClass, ContainerClass >(DataFile, goodTree); // Compare the two simulations Print("Check the particles..."); @@ -107,25 +111,21 @@ class TestSphericalWithPrevious : public FUTester<TestSphericalWithPrevious> { break; } - if(testOctreeIterator.getCurrentListSrc()->getSize() != goodOctreeIterator.getCurrentListSrc()->getSize()){ + if(testOctreeIterator.getCurrentListSrc()->getNbParticles() != goodOctreeIterator.getCurrentListSrc()->getNbParticles()){ uassert(false); break; } - ContainerClass::BasicIterator goodIter(*goodOctreeIterator.getCurrentListTargets()); - ContainerClass::BasicIterator testIter(*testOctreeIterator.getCurrentListTargets()); + const ContainerClass* testLeaf = testOctreeIterator.getCurrentListSrc(); + const ContainerClass* goodLeaf = goodOctreeIterator.getCurrentListSrc(); - while( goodIter.hasNotFinished() ){ - uassert( IsSimilar(goodIter.data().getPotential(), testIter.data().getPotential()) ); - uassert( IsSimilar(goodIter.data().getPosition().getX(), testIter.data().getPosition().getX()) ); - uassert( IsSimilar(goodIter.data().getPosition().getY(), testIter.data().getPosition().getY()) ); - uassert( IsSimilar(goodIter.data().getPosition().getZ(), testIter.data().getPosition().getZ()) ); - - goodIter.gotoNext(); - testIter.gotoNext(); + for(int idxPart = 0 ; idxPart < testLeaf->getNbParticles() ; ++idxPart ){ + uassert( IsSimilar(goodLeaf->getPotentials()[idxPart], testLeaf->getPotentials()[idxPart]) ); + uassert( IsSimilar(goodLeaf->getForcesX()[idxPart], testLeaf->getForcesX()[idxPart]) ); + uassert( IsSimilar(goodLeaf->getForcesY()[idxPart], testLeaf->getForcesY()[idxPart]) ); + uassert( IsSimilar(goodLeaf->getForcesZ()[idxPart], testLeaf->getForcesZ()[idxPart]) ); } - if(!testOctreeIterator.moveRight()){ if(goodOctreeIterator.moveRight()){ uassert(false); -- GitLab