From 799e9fc2289fda4701f751e0c2952a42a87c78b0 Mon Sep 17 00:00:00 2001
From: bramas <berenger.bramas@inria.fr>
Date: Wed, 16 Oct 2013 17:44:13 +0200
Subject: [PATCH] update TSM model using enum to enable tsm and index, but
 should be update and the result are wrong

---
 Src/Components/FBasicParticleContainer.hpp    |   3 +-
 Src/Components/FParticleType.hpp              |  24 ++
 Src/Components/FTypedLeaf.hpp                 |   9 +-
 Src/Files/FFmaTsmLoader.hpp                   |   6 +-
 Src/Files/FRandomLoader.hpp                   |   6 +-
 .../P2P/FP2PParticleContainerIndexed.hpp      |   5 +-
 Tests/Kernels/testSphericalTsmAlgorithm.cpp   |   6 +-
 Tests/Utils/testFmmAlgorithmTsm.cpp           |   6 +-
 Tests/Utils/testLoaderFMATsm.cpp              |   6 +-
 UTests/utestRotationDirectTsm.cpp             | 240 ++++++++++++++++++
 10 files changed, 292 insertions(+), 19 deletions(-)
 create mode 100644 Src/Components/FParticleType.hpp
 create mode 100644 UTests/utestRotationDirectTsm.cpp

diff --git a/Src/Components/FBasicParticleContainer.hpp b/Src/Components/FBasicParticleContainer.hpp
index 5dc496fc4..1c09c2609 100755
--- a/Src/Components/FBasicParticleContainer.hpp
+++ b/Src/Components/FBasicParticleContainer.hpp
@@ -21,6 +21,7 @@
 #include "../Utils/FAlignedMemory.hpp"
 #include "../Utils/FMath.hpp"
 #include "../Utils/FPoint.hpp"
+#include "FParticleType.hpp"
 
 /**
 * @author Berenger Bramas (berenger.bramas@inria.fr)
@@ -200,7 +201,7 @@ public:
      * Push called usually by FTypedLeaf with the isTarget flag in addition
      */
     template<typename... Args>
-    void push(const FPoint& inParticlePosition, const bool /*isTarget*/, Args... args){
+    void push(const FPoint& inParticlePosition, const FParticleType /*particleType*/, Args... args){
         push(inParticlePosition, args...);
     }
 
diff --git a/Src/Components/FParticleType.hpp b/Src/Components/FParticleType.hpp
new file mode 100644
index 000000000..8edd0d892
--- /dev/null
+++ b/Src/Components/FParticleType.hpp
@@ -0,0 +1,24 @@
+// ===================================================================================
+// 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 FPARTICLETYPE_HPP
+#define FPARTICLETYPE_HPP
+
+enum FParticleType {
+    FParticleTypeSource = 0,
+    FParticleTypeTarget = 1
+};
+
+#endif // FPARTICLETYPE_HPP
diff --git a/Src/Components/FTypedLeaf.hpp b/Src/Components/FTypedLeaf.hpp
index 8f5906016..1fc1a65d1 100755
--- a/Src/Components/FTypedLeaf.hpp
+++ b/Src/Components/FTypedLeaf.hpp
@@ -19,6 +19,8 @@
 
 #include "../Utils/FAssertable.hpp"
 #include "FAbstractLeaf.hpp"
+#include "FParticleType.hpp"
+
 
 /**
 * @author Berenger Bramas (berenger.bramas@inria.fr)
@@ -36,6 +38,7 @@ class FTypedLeaf  : public FAbstractLeaf<ContainerClass>, public FAssertable {
     ContainerClass targets; //< The targets containers
 
 public:
+
     /** Default destructor */
     virtual ~FTypedLeaf(){
     }
@@ -47,9 +50,9 @@ public:
         * followed by other param given by the user
         */
     template<typename... Args>
-    void push(const FPoint& inParticlePosition, const bool isTarget, Args ... args){
-        if(isTarget) targets.push(inParticlePosition, isTarget, args...);
-        else sources.push(inParticlePosition, isTarget, args...);
+    void push(const FPoint& inParticlePosition, const FParticleType type, Args ... args){
+        if(type == FParticleTypeTarget) targets.push(inParticlePosition, FParticleTypeTarget, args...);
+        else sources.push(inParticlePosition, FParticleTypeSource, args...);
     }
 
     /**
diff --git a/Src/Files/FFmaTsmLoader.hpp b/Src/Files/FFmaTsmLoader.hpp
index e372cdcdc..4c5356ee0 100755
--- a/Src/Files/FFmaTsmLoader.hpp
+++ b/Src/Files/FFmaTsmLoader.hpp
@@ -23,6 +23,7 @@
 #include "../Utils/FGlobal.hpp"
 #include "FAbstractLoader.hpp"
 #include "../Utils/FPoint.hpp"
+#include "../Components/FParticleType.hpp"
 
 /**
 * @author Berenger Bramas (berenger.bramas@inria.fr)
@@ -122,14 +123,15 @@ public:
       * @warning to work with the loader, particles has to expose a setPosition method
       * @param the particle to fill
       */
-    void fillParticle(FPoint*const inParticlePositions, FReal*const inPhysicalValue, bool*const inIsTarget){
+    void fillParticle(FPoint*const inParticlePositions, FReal*const inPhysicalValue, FParticleType*const particleType){
         FReal x,y,z,data;
         int isTarget;
         this->file >> x >> y >> z >> data >> isTarget;
 
         inParticlePositions->setPosition(x,y,z);
         *inPhysicalValue = data;
-        *inIsTarget = isTarget;
+        if(isTarget) (*particleType) = FParticleTypeTarget;
+        else (*particleType) = FParticleTypeSource;
     }
 
 };
diff --git a/Src/Files/FRandomLoader.hpp b/Src/Files/FRandomLoader.hpp
index 21fce59d6..7b59de0e5 100755
--- a/Src/Files/FRandomLoader.hpp
+++ b/Src/Files/FRandomLoader.hpp
@@ -25,6 +25,7 @@
 
 #include "FAbstractLoader.hpp"
 #include "../Utils/FPoint.hpp"
+#include "../Components/FParticleType.hpp"
 
 /**
 * @author Berenger Bramas (berenger.bramas@inria.fr)
@@ -114,9 +115,10 @@ public:
     }
 
 
-    void fillParticle(FPoint*const inParticlePositions, bool*const isTarget){
+    void fillParticle(FPoint*const inParticlePositions, FParticleType*const isTarget){
         FRandomLoader::fillParticle(inParticlePositions);
-        (*isTarget) = (FRandomLoader::getRandom() > 0.5 );
+        if(FRandomLoader::getRandom() > 0.5 ) (*isTarget) = FParticleTypeTarget;
+        else (*isTarget) = FParticleTypeSource;
     }
 };
 
diff --git a/Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp b/Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp
index 6ec6097b9..a74440e46 100644
--- a/Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp
+++ b/Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp
@@ -4,6 +4,7 @@
 #include "../../Containers/FVector.hpp"
 
 #include "FP2PParticleContainer.hpp"
+#include "../../Components/FParticleType.hpp"
 
 class FP2PParticleContainerIndexed : public FP2PParticleContainer {
     typedef FP2PParticleContainer Parent;
@@ -18,8 +19,8 @@ public:
     }
 
     template<typename... Args>
-    void push(const FPoint& inParticlePosition, const bool isTarget, const int index, Args... args){
-        Parent::push(inParticlePosition, isTarget, args... );
+    void push(const FPoint& inParticlePosition, const FParticleType particleType, const int index, Args... args){
+        Parent::push(inParticlePosition, particleType, args... );
         indexes.push(index);
     }
 
diff --git a/Tests/Kernels/testSphericalTsmAlgorithm.cpp b/Tests/Kernels/testSphericalTsmAlgorithm.cpp
index f953cb7dc..bda26e84d 100755
--- a/Tests/Kernels/testSphericalTsmAlgorithm.cpp
+++ b/Tests/Kernels/testSphericalTsmAlgorithm.cpp
@@ -83,9 +83,9 @@ int main(int argc, char ** argv){
     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 );
+        FParticleType particleType;
+        loader.fillParticle(&particlePosition,&physicalValue,&particleType);
+        tree.insert(particlePosition, particleType, physicalValue );
     }
 
     counter.tac();
diff --git a/Tests/Utils/testFmmAlgorithmTsm.cpp b/Tests/Utils/testFmmAlgorithmTsm.cpp
index 1355b4f19..5dd9f0259 100755
--- a/Tests/Utils/testFmmAlgorithmTsm.cpp
+++ b/Tests/Utils/testFmmAlgorithmTsm.cpp
@@ -83,10 +83,10 @@ int main(int argc, char ** argv){
 
     {
         FPoint particlePosition;
-        bool isTarget;
+        FParticleType particleType;
         for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
-            loader.fillParticle(&particlePosition, &isTarget);
-            tree.insert(particlePosition, isTarget);
+            loader.fillParticle(&particlePosition, &particleType);
+            tree.insert(particlePosition, particleType);
         }
     }
 
diff --git a/Tests/Utils/testLoaderFMATsm.cpp b/Tests/Utils/testLoaderFMATsm.cpp
index 747150d33..f1fcd19c9 100755
--- a/Tests/Utils/testLoaderFMATsm.cpp
+++ b/Tests/Utils/testLoaderFMATsm.cpp
@@ -72,10 +72,10 @@ int main(int argc, char ** argv ){
 
         FPoint particlePosition;
         FReal physicalValue = 0.0;
-        bool isTarget;
+        FParticleType particleType;
         for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
-            loader.fillParticle(&particlePosition,&physicalValue, &isTarget);
-            tree.insert(particlePosition, isTarget, physicalValue);
+            loader.fillParticle(&particlePosition,&physicalValue, &particleType);
+            tree.insert(particlePosition, particleType, physicalValue);
         }
 
         counter.tac();
diff --git a/UTests/utestRotationDirectTsm.cpp b/UTests/utestRotationDirectTsm.cpp
new file mode 100644
index 000000000..12152da32
--- /dev/null
+++ b/UTests/utestRotationDirectTsm.cpp
@@ -0,0 +1,240 @@
+
+// ===================================================================================
+// 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 "../Src/Utils/FGlobal.hpp"
+
+#include "../Src/Containers/FOctree.hpp"
+#include "../Src/Containers/FVector.hpp"
+
+#include "../Src/Kernels/Rotation/FRotationCell.hpp"
+#include "../Src/Kernels/P2P/FP2PParticleContainerIndexed.hpp"
+
+#include "../Src/Components/FTypedLeaf.hpp"
+#include "../Src/Extensions/FExtendCellType.hpp"
+#include "../Src/Kernels/Rotation/FRotationKernel.hpp"
+
+#include "../Src/Files/FRandomLoader.hpp"
+
+#include "../Src/Core/FFmmAlgorithmThreadTsm.hpp"
+#include "../Src/Core/FFmmAlgorithmTsm.hpp"
+
+#include "FUTester.hpp"
+
+
+/** the test class the rotation and target source model.
+  *
+  */
+class TestRotationDirectTsm : public FUTester<TestRotationDirectTsm> {
+    /** The test method to factorize all the test based on different kernels */
+    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
+        // Load particles
+        const int nbSources = 5000;
+        const int nbTargets = 5000;
+
+        FRandomLoader loader(nbSources + nbTargets);
+
+        Print("Number of particles:");
+        Print(loader.getNumberOfParticles());
+
+        const int NbLevels      = 4;
+        const int SizeSubLevels = 2;
+
+
+        struct TestParticle{
+            FPoint position;
+            FReal forces[3];
+            FReal physicalValue;
+            FReal potential;
+        };
+
+        TestParticle* const particlesSources = new TestParticle[nbSources];
+        TestParticle* const particlesTargets = new TestParticle[nbTargets];
+
+        // Create octree
+        OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox());
+
+        const FReal physicalValue = 0.10;
+
+        for(int idxPart = 0 ; idxPart < nbTargets ; ++idxPart){
+            FPoint position;
+            loader.fillParticle(&position);
+            // put in tree
+            tree.insert(position, FParticleTypeTarget, idxPart, physicalValue);
+            // get copy
+            particlesTargets[idxPart].position = position;
+            particlesTargets[idxPart].potential = 0.0;
+            particlesTargets[idxPart].physicalValue = physicalValue;
+            particlesTargets[idxPart].forces[0] = 0.0;
+            particlesTargets[idxPart].forces[1] = 0.0;
+            particlesTargets[idxPart].forces[2] = 0.0;
+        }
+
+        for(int idxPart = 0 ; idxPart < nbSources ; ++idxPart){
+            FPoint position;
+            loader.fillParticle(&position);
+            // put in tree
+            tree.insert(position, FParticleTypeSource, idxPart, physicalValue);
+            // get copy
+            particlesSources[idxPart].position = position;
+            particlesSources[idxPart].physicalValue = physicalValue;
+        }
+
+
+        // Run FMM
+        Print("Fmm...");
+        //KernelClass kernels(NbLevels,loader.getBoxWidth());
+        KernelClass kernels(NbLevels,loader.getBoxWidth(), loader.getCenterOfBox());
+        FmmClass algo(&tree,&kernels);
+        algo.execute();
+
+        // Run direct computation
+        Print("Direct...");
+        for(int idxTarget = 0 ; idxTarget < nbTargets ; ++idxTarget){
+            for(int idxOther = 0 ; idxOther < nbSources ; ++idxOther){
+                FP2P::NonMutualParticles(
+                            particlesSources[idxOther].position.getX(), particlesSources[idxOther].position.getY(),
+                            particlesSources[idxOther].position.getZ(),particlesSources[idxOther].physicalValue,
+                              particlesTargets[idxTarget].position.getX(), particlesTargets[idxTarget].position.getY(),
+                              particlesTargets[idxTarget].position.getZ(),particlesTargets[idxTarget].physicalValue,
+                              &particlesTargets[idxTarget].forces[0],&particlesTargets[idxTarget].forces[1],
+                              &particlesTargets[idxTarget].forces[2],&particlesTargets[idxTarget].potential);
+            }
+        }
+
+        // Compare
+        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){
+                if( leaf->getTargets()->getNbParticles() ){
+                    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(particlesTargets[indexPartOrig].potential,potentials[idxPart]);
+                        fx.add(particlesTargets[indexPartOrig].forces[0],forcesX[idxPart]);
+                        fy.add(particlesTargets[indexPartOrig].forces[1],forcesY[idxPart]);
+                        fz.add(particlesTargets[indexPartOrig].forces[2],forcesZ[idxPart]);
+                    }
+                }
+            });
+        }
+
+        delete[] particlesTargets;
+        delete[] particlesSources;
+
+        // Print for information
+        Print("Potential diff is = ");
+        Print(potentialDiff.getL2Norm());
+        Print(potentialDiff.getInfNorm());
+        Print("Fx diff is = ");
+        Print(fx.getL2Norm());
+        Print(fx.getInfNorm());
+        Print("Fy diff is = ");
+        Print(fy.getL2Norm());
+        Print(fy.getInfNorm());
+        Print("Fz diff is = ");
+        Print(fz.getL2Norm());
+        Print(fz.getInfNorm());
+
+        // Assert
+        const FReal MaximumDiff = FReal(0.0001);
+        uassert(potentialDiff.getL2Norm() < MaximumDiff);
+        uassert(potentialDiff.getInfNorm() < MaximumDiff);
+        uassert(fx.getL2Norm()  < MaximumDiff);
+        uassert(fx.getInfNorm() < MaximumDiff);
+        uassert(fy.getL2Norm()  < MaximumDiff);
+        uassert(fy.getInfNorm() < MaximumDiff);
+        uassert(fz.getL2Norm()  < MaximumDiff);
+        uassert(fz.getInfNorm() < MaximumDiff);
+    }
+
+    /** If memstas is running print the memory used */
+    void PostTest() {
+        if( FMemStats::controler.isUsed() ){
+            std::cout << "Memory used at the end " << FMemStats::controler.getCurrentAllocated() << " Bytes (" << FMemStats::controler.getCurrentAllocatedMB() << "MB)\n";
+            std::cout << "Max memory used " << FMemStats::controler.getMaxAllocated() << " Bytes (" << FMemStats::controler.getMaxAllocatedMB() << "MB)\n";
+            std::cout << "Total memory used " << FMemStats::controler.getTotalAllocated() << " Bytes (" << FMemStats::controler.getTotalAllocatedMB() << "MB)\n";
+        }
+    }
+
+    ///////////////////////////////////////////////////////////
+    // The tests!
+    ///////////////////////////////////////////////////////////
+
+    static const int P = 9;
+
+    template <const int P>
+    class CustomTypedRotationCell : public FRotationCell<P>, public FExtendCellType{
+    };
+
+    /** Rotation */
+    void TestRotation(){
+        typedef CustomTypedRotationCell<P>    CellClass;
+        typedef FP2PParticleContainerIndexed  ContainerClass;
+
+        typedef FRotationKernel<CellClass, ContainerClass, P >          KernelClass;
+
+        typedef FTypedLeaf<ContainerClass >                     LeafClass;
+        typedef FOctree< CellClass, ContainerClass , LeafClass >  OctreeClass;
+
+        typedef FFmmAlgorithmTsm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass;
+
+        RunTest<CellClass, ContainerClass, KernelClass, LeafClass, OctreeClass, FmmClass>();
+    }
+
+    void TestRotationThread(){
+        typedef CustomTypedRotationCell<P>    CellClass;
+        typedef FP2PParticleContainerIndexed  ContainerClass;
+
+        typedef FRotationKernel<CellClass, ContainerClass, P >          KernelClass;
+
+        typedef FTypedLeaf<ContainerClass >                     LeafClass;
+        typedef FOctree< CellClass, ContainerClass , LeafClass >  OctreeClass;
+
+        typedef FFmmAlgorithmThreadTsm<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass;
+
+        RunTest<CellClass, ContainerClass, KernelClass, LeafClass, OctreeClass, FmmClass>();
+    }
+
+    ///////////////////////////////////////////////////////////
+    // Set the tests!
+    ///////////////////////////////////////////////////////////
+
+    /** set test */
+    void SetTests(){
+        AddTest(&TestRotationDirectTsm::TestRotation,"Test Rotation Kernel TSM");
+        AddTest(&TestRotationDirectTsm::TestRotation,"Test Rotation Kernel TSM thread");
+    }
+};
+
+
+// You must do this
+TestClass(TestRotationDirectTsm)
+
+
+
-- 
GitLab