diff --git a/Sources/Core/FAbstractCell.hpp b/Sources/Core/FAbstractCell.hpp
index 8b418bfefffb9094c19de775690284466e549ecf..80cc533509ae9945d7da73bb3767e33247113d26 100644
--- a/Sources/Core/FAbstractCell.hpp
+++ b/Sources/Core/FAbstractCell.hpp
@@ -11,6 +11,12 @@
 *
 * This class define the method that every cell class
 * has to implement.
+*
+* In fact FOctree & FFMMAlgorithm need this function to be implemented.
+* But you cannot use this interface with the extension (as an example :
+* because the compiler will faill to know if getMortonIndex is coming
+* from this interface or from the extension)
+*
 * @warning Inherite from this class when implement a specific cell type
 */
 class FAbstractCell{
diff --git a/Sources/Core/FAbstractParticule.hpp b/Sources/Core/FAbstractParticule.hpp
index 5b0034253fabf30c3b935bdafd0b7734f6eaa13d..803fe390c68fffa772c45afb217f0876dfa905b7 100644
--- a/Sources/Core/FAbstractParticule.hpp
+++ b/Sources/Core/FAbstractParticule.hpp
@@ -13,6 +13,13 @@ class F3DPosition;
 *
 * This class define the method that every particule class
 * has to implement.
+*
+* In fact FOctree & FFMMAlgorithm need this function to be implemented.
+* But you cannot use this interface with the extension (as an example :
+* because the compiler will faill to know if getPosition is coming
+* from this interface or from the extension)
+*
+*
 * @warning Inherite from this class when implement a specific particule type
 */
 class FAbstractParticule{
diff --git a/Sources/Core/FBasicCell.hpp b/Sources/Core/FBasicCell.hpp
index 2ab33ad6ae33c1ccef0c32004abe5f4794e760cd..09d8401f1a978707c7bcb5a0dd868970b166b432 100644
--- a/Sources/Core/FBasicCell.hpp
+++ b/Sources/Core/FBasicCell.hpp
@@ -2,59 +2,25 @@
 #define FBASICCELL_HPP
 // /!\ Please, you must read the license at the bottom of this page
 
-#include "FAbstractCell.hpp"
-#include "../Containers/FTreeCoordinate.hpp"
+#include "FExtendPosition.hpp"
+#include "FExtendMortonIndex.hpp"
 
 /**
 * @author Berenger Bramas (berenger.bramas@inria.fr)
 * @class FBasicCell
 * Please read the license
 *
-* This class defines a basic cell used for examples.
+* This class defines a basic cell used for examples. It extends
+* the mininum, only what is needed by FOctree and FFMMAlgorithm
+* to make the things working.
+* By using this extension it will implement the FAbstractCell without
+* inheriting from it.
 */
-class FBasicCell : public FAbstractCell {
-protected:
-    MortonIndex index;    //< Cell's position in the tree
-    F3DPosition position; //< Cell's spacial position
-
+class FBasicCell : public FExtendPosition, public FExtendMortonIndex {
 public:
-    /** Default constructor */
-    FBasicCell() : index(0), position(0,0,0){
-    }
-
     /** Default destructor */
     virtual ~FBasicCell(){
     }
-
-    /**
-    * From the FAbstractParticule definition
-    * @return the position of the current cell
-    */
-    MortonIndex getMortonIndex() const {
-        return this->index;
-    }
-
-    /**
-      * This function is needed by the basic loader to fill the current particule
-      * @param inPos the position given by the basic loader
-      */
-    void setMortonIndex(const MortonIndex inIndex) {
-        this->index = inIndex;
-    }
-
-    /**
-    * @return the position of the current cell
-    */
-    F3DPosition getPosition() const{
-        return this->position;
-    }
-
-    /**
-    * @param inPosition the position of the current cell
-    */
-    void setPosition(const F3DPosition& inPosition){
-        this->position = inPosition;
-    }
 };
 
 
diff --git a/Sources/Core/FBasicKernels.hpp b/Sources/Core/FBasicKernels.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..2601bf256714403ab33e02a488965e4757e23844
--- /dev/null
+++ b/Sources/Core/FBasicKernels.hpp
@@ -0,0 +1,62 @@
+#ifndef FBASICKERNELS_HPP
+#define FBASICKERNELS_HPP
+// /!\ Please, you must read the license at the bottom of this page
+
+#include "FAbstractKernels.hpp"
+
+#include "../Utils/FDebug.hpp"
+
+/**
+* @author Berenger Bramas (berenger.bramas@inria.fr)
+* @class AbstractKernels
+* @brief
+* Please read the license
+*
+* This kernels simply shows the details of the information
+* it receives (in debug)
+*/
+template< class ParticuleClass, class CellClass>
+class FBasicKernels : public FAbstractKernels<ParticuleClass,CellClass> {
+public:
+    /** Default destructor */
+    virtual ~FBasicKernels(){
+    }
+
+    /** When init the kernel */
+    virtual void init(){}
+
+    /** Print the number of particules */
+    virtual void P2M(CellClass* const pole, FList<ParticuleClass*>* const particules) {
+        FDEBUG( FDebug::Controller << "P2M : " << particules->getSize() << "\n" );
+    }
+
+    /** Print the morton index */
+    virtual void M2M(CellClass* const pole, CellClass** const child, const int inLevel) {
+        FDEBUG( FDebug::Controller << "M2M : " << pole->getMortonIndex() << "\n" );
+    }
+
+    /** Print the morton index */
+    virtual void M2L(CellClass* const pole, CellClass** const distantNeighbors, const int size, const int inLevel) {
+        FDEBUG( FDebug::Controller << "M2L : " << pole->getMortonIndex() << " (" << size << ")\n" );
+    }
+
+    /** Print the morton index */
+    virtual void L2L(CellClass* const pole, CellClass** const child, const int inLevel) {
+        FDEBUG( FDebug::Controller << "L2L : " << pole->getMortonIndex() << "\n" );
+    }
+
+    /** Print the number of particules */
+    virtual void L2P(CellClass* const pole, FList<ParticuleClass*>* const particules){
+        FDEBUG( FDebug::Controller << "L2P : " << particules->getSize() << "\n" );
+    }
+
+    /** Print the number of particules */
+    virtual void P2P(FList<ParticuleClass*>* const currentBox, FList<ParticuleClass*>** directNeighbors, const int size) {
+        FDEBUG( FDebug::Controller << "P2P : " << currentBox->getSize() << " (" << size << ")\n" );
+    }
+};
+
+
+#endif //FBASICKERNELS_HPP
+
+// [--LICENSE--]
diff --git a/Sources/Core/FBasicParticule.hpp b/Sources/Core/FBasicParticule.hpp
index c6306939712627479c951ef7ede0c5f36d94cbb6..d6692d7a145b7750c29a30676a0f89b4bfec98d0 100644
--- a/Sources/Core/FBasicParticule.hpp
+++ b/Sources/Core/FBasicParticule.hpp
@@ -2,60 +2,24 @@
 #define FBASICPARTICULE_HPP
 // /!\ Please, you must read the license at the bottom of this page
 
-#include "FAbstractParticule.hpp"
-#include "../Utils/F3DPosition.hpp"
+#include "FExtendPosition.hpp"
 
 /**
 * @author Berenger Bramas (berenger.bramas@inria.fr)
 * @class FBasicParticule
 * Please read the license
 *
-* This class defines a basic particule used for examples.
+* This class defines a basic particule 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 FAbstractParticule without
+* inheriting from it.
 */
-class FBasicParticule : public FAbstractParticule{
-protected:
-    F3DPosition pos;    //< Particule's position
-
+class FBasicParticule : public FExtendPosition{
 public:
-    /**
-    * Constructor with a position
-    * @param inX x position
-    * @param inY y position
-    * @param inZ z position
-    */
-    FBasicParticule(const double inX, const double inY, const double inZ) : pos(inX,inY,inZ) {
-    }
-
-    /**
-    * Constructor with a position object
-    * @param inPos particule position
-    */
-    FBasicParticule(const F3DPosition& inPos) : pos(inPos) {
-    }
-
-    /** Default constructor */
-    FBasicParticule(){
-    }
-
     /** Default destructor */
     virtual ~FBasicParticule(){
     }
-
-    /**
-    * From the FAbstractParticule definition
-    * @return the position of the current cell
-    */
-    F3DPosition getPosition() const {
-        return pos;
-    }
-
-    /**
-      * This function is needed by the basic loader to fill the current particule
-      * @param inPos the position given by the basic loader
-      */
-    void setPosition(const F3DPosition& inPos) {
-        pos = inPos;
-    }
 };
 
 
diff --git a/Sources/Core/FExtendForces.hpp b/Sources/Core/FExtendForces.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..bacdfbe1772403c9bf0d303a770859fddf8015ac
--- /dev/null
+++ b/Sources/Core/FExtendForces.hpp
@@ -0,0 +1,60 @@
+#ifndef FEXTENDFORCES_HPP
+#define FEXTENDFORCES_HPP
+// /!\ Please, you must read the license at the bottom of this page
+
+#include "../Utils/F3DPosition.hpp"
+
+/**
+* @author Berenger Bramas (berenger.bramas@inria.fr)
+* @class FExtendForces
+* Please read the license
+*
+* This class is an extenssion.
+* It proposes a 3d array as a forces vector.
+*/
+class FExtendForces {
+protected:
+    F3DPosition forces; //< 3D vector stored in a position object
+
+public:
+    /** Default constructor */
+    FExtendForces() {
+    }
+
+    /** Copy constructor */
+    FExtendForces(const FExtendForces& other) : forces(other.forces) {
+    }
+
+    /** Destructor */
+    virtual ~FExtendForces(){
+    }
+
+    /** Copy operator */
+    FExtendForces& operator=(const FExtendForces& other) {
+        this->forces = other.forces;
+        return *this;
+    }
+
+    /** Return the forces */
+    F3DPosition getForces() const {
+        return this->forces;
+    }
+
+    /** Set Forces */
+    void setForces(const F3DPosition& inForces) {
+        this->forces = inForces;
+    }
+
+    /** Set Forces with 3 doubles */
+    void setForces(const double inFx, const double inFy, const double inFz) {
+        this->forces.setX(inFx);
+        this->forces.setY(inFy);
+        this->forces.setZ(inFz);
+    }
+
+};
+
+
+#endif //FEXTENDFORCES_HPP
+
+// [--LICENSE--]
diff --git a/Sources/Core/FExtendMortonIndex.hpp b/Sources/Core/FExtendMortonIndex.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7e7d5c0523f01a4de1d819bf72051e029a1ad315
--- /dev/null
+++ b/Sources/Core/FExtendMortonIndex.hpp
@@ -0,0 +1,52 @@
+#ifndef FEXTENDMORTONINDEX_HPP
+#define FEXTENDMORTONINDEX_HPP
+// /!\ Please, you must read the license at the bottom of this page
+
+#include "../Containers/FTreeCoordinate.hpp"
+
+/**
+* @author Berenger Bramas (berenger.bramas@inria.fr)
+* @class FExtendMortonIndex
+* Please read the license
+* This class is an extenssion.
+* It proposes a mortonIndex.
+*/
+class FExtendMortonIndex {
+protected:
+    MortonIndex mortonIndex;    //< Morton index (need by most elements)
+
+public:
+    /** Default constructor */
+    FExtendMortonIndex() : mortonIndex(0) {
+    }
+
+    /** Copy constructor */
+    FExtendMortonIndex(const FExtendMortonIndex& other) : mortonIndex(other.mortonIndex) {
+    }
+
+    /** Destructor */
+    virtual ~FExtendMortonIndex(){
+    }
+
+    /** Copy operator */
+    FExtendMortonIndex& operator=(const FExtendMortonIndex& other) {
+        this->mortonIndex = other.mortonIndex;
+        return *this;
+    }
+
+    /** To get the morton index */
+    MortonIndex getMortonIndex() const {
+        return this->mortonIndex;
+    }
+
+    /** To set the morton index */
+    void setMortonIndex(const MortonIndex inMortonIndex) {
+        this->mortonIndex = inMortonIndex;
+    }
+
+};
+
+
+#endif //FEXTENDMORTONINDEX_HPP
+
+// [--LICENSE--]
diff --git a/Sources/Core/FExtendPosition.hpp b/Sources/Core/FExtendPosition.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3688dec3fd3e48700bb971877ebc95b1d8fb1d44
--- /dev/null
+++ b/Sources/Core/FExtendPosition.hpp
@@ -0,0 +1,59 @@
+#ifndef FEXTENDPOSITION_HPP
+#define FEXTENDPOSITION_HPP
+// /!\ Please, you must read the license at the bottom of this page
+
+#include "../Utils/F3DPosition.hpp"
+
+/**
+* @author Berenger Bramas (berenger.bramas@inria.fr)
+* @class FExtendPosition
+* Please read the license
+* This class is an extenssion.
+* It proposes a mortonIndex.
+*/
+class FExtendPosition {
+protected:
+    F3DPosition position; //< The position
+
+public:
+    /** Default constructor */
+    FExtendPosition() {
+    }
+
+    /** Copy constructor */
+    FExtendPosition(const FExtendPosition& other) : position(other.position) {
+    }
+
+    /** Destructor */
+    virtual ~FExtendPosition(){
+    }
+
+    /** Copy operator */
+    FExtendPosition& operator=(const FExtendPosition& other) {
+        this->position = other.position;
+        return *this;
+    }
+
+    /** To get the position */
+    F3DPosition getPosition() const {
+        return this->position;
+    }
+
+    /** To set the position */
+    void setPosition(const F3DPosition& inPosition) {
+        this->position = inPosition;
+    }
+
+    /** To set the position from 3 doubles */
+    void setPosition(const double inX, const double inY, const double inZ) {
+        this->position.setX(inX);
+        this->position.setY(inY);
+        this->position.setZ(inZ);
+    }
+
+};
+
+
+#endif //FEXTENDPOSITION_HPP
+
+// [--LICENSE--]
diff --git a/Sources/Core/FExtendPotential.hpp b/Sources/Core/FExtendPotential.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..65f272af9a8cd88b1401c8ce120720c75d8fe896
--- /dev/null
+++ b/Sources/Core/FExtendPotential.hpp
@@ -0,0 +1,50 @@
+#ifndef FEXTENDPOTENTIAL_HPP
+#define FEXTENDPOTENTIAL_HPP
+// /!\ Please, you must read the license at the bottom of this page
+
+/**
+* @author Berenger Bramas (berenger.bramas@inria.fr)
+* @class FExtendPotential
+* Please read the license
+* This class is an extenssion.
+* It proposes a Potential (double).
+*/
+class FExtendPotential {
+protected:
+    double potential;   //< The potential extended
+
+public:
+    /** Default constructor */
+    FExtendPotential() : potential(0) {
+    }
+
+    /** Copy constructor */
+    FExtendPotential(const FExtendPotential& other) : potential(other.potential) {
+    }
+
+    /** Destructor */
+    virtual ~FExtendPotential(){
+    }
+
+    /** Copy operator */
+    FExtendPotential& operator=(const FExtendPotential& other) {
+        this->potential = other.potential;
+        return *this;
+    }
+
+    /** To get the potential */
+    double getPotential() const {
+        return this->potential;
+    }
+
+    /** To set the potential */
+    void setPotential(const double inPotential) {
+        this->potential = inPotential;
+    }
+
+};
+
+
+#endif //FEXTENDPOTENTIAL_HPP
+
+// [--LICENSE--]
diff --git a/Sources/Core/FExtendValue.hpp b/Sources/Core/FExtendValue.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f6aaf8ca81eea31218d32061322997da25d62145
--- /dev/null
+++ b/Sources/Core/FExtendValue.hpp
@@ -0,0 +1,50 @@
+#ifndef FEXTENDVALUE_HPP
+#define FEXTENDVALUE_HPP
+// /!\ Please, you must read the license at the bottom of this page
+
+/**
+* @author Berenger Bramas (berenger.bramas@inria.fr)
+* @class FExtendValue
+* Please read the license
+* This class is an extenssion.
+* It proposes a value (double).
+*/
+class FExtendValue {
+protected:
+    double value;   //< A simple value
+
+public:
+    /** Default constructor */
+    FExtendValue() : value(0) {
+    }
+
+    /** Copy constructor */
+    FExtendValue(const FExtendValue& other) : value(other.value) {
+    }
+
+    /** Destructor */
+    virtual ~FExtendValue(){
+    }
+
+    /** Copy Constructor */
+    FExtendValue& operator=(const FExtendValue& other) {
+        this->value = other.value;
+        return *this;
+    }
+
+    /** To get the value */
+    double getValue() const {
+        return this->value;
+    }
+
+    /** To set the value */
+    void setValue(const double invalue) {
+        this->value = invalue;
+    }
+
+};
+
+
+#endif //FEXTENDVALUE_HPP
+
+// [--LICENSE--]
diff --git a/Sources/Core/FFMMAlgorithm.hpp b/Sources/Core/FFMMAlgorithm.hpp
index d0ede7273e625e78d5d90938609c414187a6c196..cf712c6972469d7f4f31e77324b0ccf6878d4d9a 100644
--- a/Sources/Core/FFMMAlgorithm.hpp
+++ b/Sources/Core/FFMMAlgorithm.hpp
@@ -25,7 +25,7 @@ class FFMMAlgorithm : public FAssertable{
     FOctree<ParticuleClass, CellClass, OctreeHeight, SubtreeHeight>* const tree;    //< The octree to work on
     FAbstractKernels<ParticuleClass, CellClass>* const kernels;                     //< The kernels
 
-    FDEBUG(FTic counter);
+    FDEBUG_TIME(FTic counter);       //< In case of debug count the time
 
 public:	
     /** The constructor need the octree and the kernels used for computation
@@ -60,8 +60,8 @@ public:
 
     /** P2M */
     void bottomPass(){
-        FDEBUG( FDebug::Controller.write("\tStart Bottom Pass\n").write(FDebug::Flush) );
-        FDEBUG(counter.tic(););
+        FDEBUG_TRACE( FDebug::Controller.write("\tStart Bottom Pass\n").write(FDebug::Flush) );
+        FDEBUG_TIME(counter.tic(););
 
         typename FOctree<ParticuleClass, CellClass, OctreeHeight, SubtreeHeight>::Iterator octreeIterator(tree);
         // Iterate on leafs
@@ -72,14 +72,14 @@ public:
             kernels->P2M( octreeIterator.getCurrentCell() , octreeIterator.getCurrentList());
         } while(octreeIterator.moveRight());
 
-        FDEBUG(counter.tac(););
-        FDEBUG( FDebug::Controller << "\tFinished (" << counter.elapsed() << "s)\n"; )
+        FDEBUG_TIME(counter.tac(););
+        FDEBUG_TRACE( FDebug::Controller << "\tFinished (") FDEBUG_TIME(<< counter.elapsed() <<) FDEBUG_TRACE("s)\n"; )
     }
 
     /** M2M */
     void upwardPass(){
-        FDEBUG( FDebug::Controller.write("\tStart Upward Pass\n").write(FDebug::Flush); );
-        FDEBUG(counter.tic(););
+        FDEBUG_TRACE( FDebug::Controller.write("\tStart Upward Pass\n").write(FDebug::Flush); );
+        FDEBUG_TIME(counter.tic(););
 
         typename FOctree<ParticuleClass, CellClass, OctreeHeight, SubtreeHeight>::Iterator octreeIterator(tree);
         octreeIterator.gotoBottomLeft();
@@ -96,14 +96,14 @@ public:
             octreeIterator.gotoLeft();
         }
 
-        FDEBUG(counter.tac(););
-        FDEBUG( FDebug::Controller << "\tFinished (" << counter.elapsed() << "s)\n"; )
+        FDEBUG_TIME(counter.tac(););
+        FDEBUG_TRACE( FDebug::Controller << "\tFinished (") FDEBUG_TIME(<< counter.elapsed() <<) FDEBUG_TRACE("s)\n"; )
     }
 
     /** M2L L2L */
     void downardPass(){
-        FDEBUG( FDebug::Controller.write("\tStart Downward Pass (M2L)\n").write(FDebug::Flush); );
-        FDEBUG(counter.tic(););
+        FDEBUG_TRACE( FDebug::Controller.write("\tStart Downward Pass (M2L)\n").write(FDebug::Flush); );
+        FDEBUG_TIME(counter.tic(););
 
         { // first M2L
             typename FOctree<ParticuleClass, CellClass, OctreeHeight, SubtreeHeight>::Iterator octreeIterator(tree);
@@ -120,11 +120,11 @@ public:
                 octreeIterator.moveDown();
             }
         }
-        FDEBUG(counter.tac(););
-        FDEBUG( FDebug::Controller << "\tFinished (" << counter.elapsed() << "s)\n"; )
+        FDEBUG_TIME(counter.tac(););
+        FDEBUG_TRACE( FDebug::Controller << "\tFinished (") FDEBUG_TIME(<< counter.elapsed() <<) FDEBUG_TRACE("s)\n"; )
 
-        FDEBUG( FDebug::Controller.write("\tStart Downward Pass (L2L)\n").write(FDebug::Flush); );
-        FDEBUG(counter.tic(););
+        FDEBUG_TRACE( FDebug::Controller.write("\tStart Downward Pass (L2L)\n").write(FDebug::Flush); );
+        FDEBUG_TIME(counter.tic(););
         { // second L2L
             typename FOctree<ParticuleClass, CellClass, OctreeHeight, SubtreeHeight>::Iterator octreeIterator(tree);
             octreeIterator.moveDown();
@@ -140,15 +140,15 @@ public:
             }
         }
 
-        FDEBUG(counter.tac(););
-        FDEBUG( FDebug::Controller << "\tFinished (" << counter.elapsed() << "s)\n"; )
+        FDEBUG_TIME(counter.tac(););
+        FDEBUG_TRACE( FDebug::Controller << "\tFinished (") FDEBUG_TIME(<< counter.elapsed() <<) FDEBUG_TRACE("s)\n"; )
 
     }
 
     /** P2P */
     void directPass(){
-        FDEBUG( FDebug::Controller.write("\tStart Direct Pass\n").write(FDebug::Flush); );
-        FDEBUG(counter.tic(););
+        FDEBUG_TRACE( FDebug::Controller.write("\tStart Direct Pass\n").write(FDebug::Flush); );
+        FDEBUG_TIME(counter.tic(););
 
         typename FOctree<ParticuleClass, CellClass, OctreeHeight, SubtreeHeight>::Iterator octreeIterator(tree);
         octreeIterator.gotoBottomLeft();
@@ -162,8 +162,8 @@ public:
             kernels->P2P( octreeIterator.getCurrentList() , neighbors, counter);
         } while(octreeIterator.moveRight());
 
-        FDEBUG(counter.tac(););
-        FDEBUG( FDebug::Controller << "\tFinished (" << counter.elapsed() << "s)\n"; )
+        FDEBUG_TIME(counter.tac(););
+        FDEBUG_TRACE( FDebug::Controller << "\tFinished (") FDEBUG_TIME(<< counter.elapsed() <<) FDEBUG_TRACE("s)\n"; )
 
     }
 
diff --git a/Sources/Core/FFmaParticule.hpp b/Sources/Core/FFmaParticule.hpp
index d78e93acfa7f31d1f4ad43c0a8bcf8fcbb3aa67f..41d47a4ae9333092fdbe3c0e04aad813cb215531 100644
--- a/Sources/Core/FFmaParticule.hpp
+++ b/Sources/Core/FFmaParticule.hpp
@@ -3,60 +3,21 @@
 // /!\ Please, you must read the license at the bottom of this page
 
 #include "FBasicParticule.hpp"
+#include "FExtendValue.hpp"
 
 /**
 * @author Berenger Bramas (berenger.bramas@inria.fr)
 * @class FFmaParticule
 * Please read the license
 *
-* This class defines a basic particule used for examples.
+* This class defines a particule for FMA loader.
+* As defined in FFmaLoader it needs {FBasicParticule,FExtendValue}
 */
-class FFmaParticule : public FBasicParticule{
-protected:
-    double value;    //< Particule's fma data
-
+class FFmaParticule : public FBasicParticule, public FExtendValue {
 public:
-    /**
-    * Constructor with a position
-    * @param inX x position
-    * @param inY y position
-    * @param inZ z position
-    * @param inValue particule value
-    */
-    FFmaParticule(const double inX, const double inY, const double inZ, const double inValue)
-	: FBasicParticule(inX,inY,inZ), value(inValue) {
-    }
-
-    /**
-    * Constructor with a position object
-    * @param inPos particule position
-    */
-    FFmaParticule(const F3DPosition& inPos) : FBasicParticule(inPos), value(0){
-    }
-
-    /** Default constructor */
-    FFmaParticule() : value(0) {
-    }
-
     /** Default destructor */
     virtual ~FFmaParticule(){
     }
-
-    /**
-    * From the Fmb needed
-    * @return the value of the current cell
-    */
-    double getValue() const {
-        return this->value;
-    }
-
-    /**
-      * This function is needed by the fma loader to fill the current particule
-      * @param inValue the data given by the fma loader
-      */
-    void setValue(const double inValue) {
-        this->value = inValue;
-    }
 };
 
 
diff --git a/Sources/Fmb/FExtendFmbCell.hpp b/Sources/Fmb/FExtendFmbCell.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..2c682ca5768a8188a99f0c2f5db3e9410326fa98
--- /dev/null
+++ b/Sources/Fmb/FExtendFmbCell.hpp
@@ -0,0 +1,58 @@
+#ifndef FEXTENDFMBCELL_HPP
+#define FEXTENDFMBCELL_HPP
+// /!\ Please, you must read the license at the bottom of this page
+
+#include <string.h>
+
+#include "../Utils/FComplexe.hpp"
+
+/**
+* @author Berenger Bramas (berenger.bramas@inria.fr)
+* @class FExtendFmbCell
+* Please read the license
+*/
+template <int P>
+class FExtendFmbCell {
+protected:
+    static const int FMB_Info_P = P;        //< P >> FMB_Info.P
+    static const int MultipoleSize = int(((FMB_Info_P)+1) * ((FMB_Info_P)+2) * 0.5); //< The size of the multipole
+
+    FComplexe multipole_exp[MultipoleSize]; //< For multipole extenssion
+    FComplexe local_exp[MultipoleSize];     //< For local extenssion
+
+public:
+    /** Default constructor */
+    FExtendFmbCell() {
+    }
+
+    /** Constructor */
+    FExtendFmbCell(const FExtendFmbCell& other){
+        (*this) = other;
+    }
+
+    /** Default destructor */
+    virtual ~FExtendFmbCell(){
+    }
+
+    /** Copy constructor */
+    FExtendFmbCell& operator=(const FExtendFmbCell& other) {
+        memcpy(multipole_exp, other.multipole_exp, sizeof(multipole_exp));
+        memcpy(local_exp, other.local_exp, sizeof(local_exp));
+        return *this;
+    }
+
+    /** Get Multipole */
+    FComplexe* getMultipole() {
+        return this->multipole_exp;
+    }
+    /** Get Local */
+    FComplexe* getLocal() {
+        return this->local_exp;
+    }
+
+};
+
+
+#endif //FEXTENDFMBCELL_HPP
+
+// [--LICENSE--]
diff --git a/Sources/Fmb/FFmbKernels.hpp b/Sources/Fmb/FFmbKernels.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ce91004a350adea4640c460d7338cbaddb78be5e
--- /dev/null
+++ b/Sources/Fmb/FFmbKernels.hpp
@@ -0,0 +1,1160 @@
+#ifndef FFMBKERNELS_HPP
+#define FFMBKERNELS_HPP
+// /!\ Please, you must read the license at the bottom of this page
+
+#include "../Core/FAbstractKernels.hpp"
+
+#include "../Containers/FTreeCoordinate.hpp"
+#include "../Containers/FList.hpp"
+
+#include "../Utils/F3DPosition.hpp"
+#include "../Utils/FComplexe.hpp"
+#include "../Utils/FMath.hpp"
+
+#include <iostream>
+
+
+/**
+* @author Berenger Bramas (berenger.bramas@inria.fr)
+* @class AbstractKernels
+* @brief
+* Please read the license
+*
+* This kernels simply shows the details of the information
+* it receives
+*/
+template< class ParticuleClass, class CellClass>
+class FFmbKernels : public FAbstractKernels<ParticuleClass,CellClass> {
+    // P is a input parameter
+    static const int FMB_Info_P = 2;
+
+    //#ifdef _GRAVITATIONAL_
+    static const int FMB_Info_eps_soft_square = 1;
+    // else = 0
+    //#endif
+
+    // LMax is used in several algorithm
+    // it is just a copy of FMB_Info.P
+    static const int LMax = FMB_Info_P;
+
+    // Can be 2 * FMB_Info_P if user ask to
+    static const int FMB_Info_M2L_P = FMB_Info_P;
+    static const int FMB_Info_M2L_exp_size = ((FMB_Info_M2L_P)+1) * ((FMB_Info_M2L_P)+2) * 0.5;
+
+    // Default value set in main
+    static const int FMB_Info_ws = 1;
+
+    // INTERACTION_LIST_SIZE_ALONG_1_DIM
+    static const int size1Dim =  (2*(2*(FMB_Info_ws)+1) +1);
+    // HALF_INTERACTION_LIST_SIZE_ALONG_1_DIM
+    static const int halphSize1Dim =  (2*(FMB_Info_ws)+1);
+
+    // EXPANSION_SIZE(FMB_Info.P)
+    static const int FMB_Info_exp_size = ((FMB_Info_P)+1) * ((FMB_Info_P)+2) * 0.5;
+    // NEXP_SIZE(FMB_Info.P)
+    static const int FMB_Info_nexp_size = (FMB_Info_P + 1) * (FMB_Info_P + 1);
+
+    // Level of the tree
+    const int treeHeight;
+    // Width of the box at the root level
+    const double treeWidthAtRoot;
+
+    // transfer_M2M_container
+    FComplexe*** transitionM2M;
+    // transfer_L2L_container
+    FComplexe*** transitionL2L;
+
+    // transfer_container
+    FComplexe***** transferM2L;
+
+    //[OK] spherical_harmonic_Outer_coefficients_array
+    double sphereHarmoOuterCoef[FMB_Info_exp_size];
+    //[OK] spherical_harmonic_Inner_coefficients_array
+    double sphereHarmoInnerCoef[FMB_Info_exp_size];
+
+    FComplexe current_thread_Y[FMB_Info_exp_size];
+
+    // p_Y_theta_derivated
+    FComplexe current_thread_Y_theta_derivated[FMB_Info_exp_size];
+
+    // [OK?] p_precomputed_cos_and_sin_array
+    FComplexe cosSin[FMB_Info_M2L_P + 1];
+    // [OK?] p_associated_Legendre_function_Array
+    double legendre[FMB_Info_M2L_exp_size];
+
+    // pow_of_I_array
+    static const double PiArrayInner[4];
+    // pow_of_O_array
+    static const double PiArrayOuter[4];
+
+    // To store spherical position
+    struct Spherical {
+        double r, cosTheta, sinTheta, phi;
+    };
+
+    int expansion_Redirection_array_for_j[FMB_Info_M2L_P + 1 ];
+
+    F3DPosition force_sum;
+    double potential_sum;
+
+    //////////////////////////////////////////////////////////////////
+    // Allocation
+    //////////////////////////////////////////////////////////////////
+
+    void expansion_Redirection_array_for_j_Initialize() {
+            for( int h = 0; h <= FMB_Info_M2L_P ; ++h ){
+                expansion_Redirection_array_for_j[h] = static_cast<int>( h * ( h + 1 ) * 0.5 );
+            }
+    }
+
+    //spherical_harmonic_Outer_and_Inner_coefficients_array_Initialize
+    void sphericalHarmonicInitialize(){
+        // Outer coefficients:
+        //std::cout << "sphereHarmoOuterCoef\n";
+        double factOuter = 1.0;
+        // in FMB code stoped at <= FMB_Info_M2L_P but this is not sufficient
+        for(int idxP = 0 ; idxP < FMB_Info_exp_size; factOuter *= (++idxP) ){
+            this->sphereHarmoOuterCoef[idxP] = factOuter;
+            //std::cout << this->sphereHarmoOuterCoef[idxl] << "\n";
+        }
+
+        // Inner coefficients:
+        double* currentInner = this->sphereHarmoInnerCoef;
+        double factInner = 1.0;
+        double powN1idxP = 1.0;
+        //std::cout << "sphereHarmoInnerCoef\n";
+        for(int idxP = 0 ; idxP <= this->FMB_Info_M2L_P ; factInner *= (++idxP), powN1idxP = -powN1idxP){
+            for(int idxMP = 0, fact_l_m = factInner; idxMP <= idxP ; fact_l_m *= idxP+(++idxMP), ++currentInner){
+                *currentInner = powN1idxP / fact_l_m;
+                //std::cout << (*currentInner) << "\n";
+            }
+        }
+
+        //for(int temp = 0 ; temp < 6 ; ++temp){
+        //    std::cout << this->sphereHarmoInnerCoef[temp] << "\n";
+        //}
+    }
+
+
+    // transfer_L2L_Allocate
+    // transfer_M2M_Allocate
+    // transfer_M2L_Allocate
+    void transferAllocate(){
+        // M2M L2L
+        this->transitionM2M = new FComplexe**[this->treeHeight];
+        this->transitionL2L = new FComplexe**[this->treeHeight];
+
+        for(int idxLevel = 0 ; idxLevel < this->treeHeight ; ++idxLevel){
+
+            this->transitionM2M[idxLevel] = new FComplexe*[8];
+            this->transitionL2L[idxLevel] = new FComplexe*[8];
+
+            for(long idxChild = 0; idxChild < 8; ++idxChild){
+                this->transitionM2M[idxLevel][idxChild] = new FComplexe[FMB_Info_exp_size];
+                this->transitionL2L[idxLevel][idxChild] = new FComplexe[FMB_Info_exp_size];
+            }
+        }
+        // M2L
+        this->transferM2L = new FComplexe****[this->treeHeight+1];
+
+        for(int idxLevel = 0; idxLevel < this->treeHeight; ++idxLevel){
+            this->transferM2L[idxLevel] = new FComplexe***[this->size1Dim];
+
+            for(long idxD1 = 0 ; idxD1 < this->size1Dim; ++idxD1){
+                this->transferM2L[idxLevel][idxD1] = new FComplexe**[this->size1Dim];
+
+                for(long idxD2 = 0; idxD2 < this->size1Dim; ++idxD2){
+                    this->transferM2L[idxLevel][idxD1][idxD2] = new FComplexe*[this->size1Dim];
+
+                    for(long idxD3 = 0; idxD3 < this->size1Dim; ++idxD3){
+                        const int x = idxD1 - this->halphSize1Dim;
+                        const int y = idxD2 - this->halphSize1Dim;
+                        const int z = idxD3 - this->halphSize1Dim;
+
+                        if( ( x*x + y*y + z*z ) >= ( 3*this->FMB_Info_ws*this->FMB_Info_ws + 0.1 ) ){
+                            //[Blas] this->transferM2L[idxLevel][idxD1][idxD2][idxD3] = new FComplexe[this->FMB_Info_exp_size * this->FMB_Info_nexp_size];
+                            this->transferM2L[idxLevel][idxD1][idxD2][idxD3] = new FComplexe[this->FMB_Info_M2L_exp_size];
+                        }
+                        else {
+                            this->transferM2L[idxLevel][idxD1][idxD2][idxD3] = NULL;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    // transfer_L2L_free
+    // transfer_M2M_free
+    // transfer_M2L_free
+    void transferDeallocate(){
+        // M2M L2L
+        for(long idxLevel = 0 ; idxLevel < this->treeHeight ; ++idxLevel){
+            for(long idxChild = 0; idxChild < 8; ++idxChild){
+                delete [] this->transitionM2M[idxLevel][idxChild];
+                delete [] this->transitionL2L[idxLevel][idxChild];
+            }
+            delete [] this->transitionM2M[idxLevel];
+            delete [] transitionL2L[idxLevel];
+        }
+        delete [] this->transitionM2M;
+        delete [] this->transitionL2L;
+        // M2L
+        for(int idxLevel = 0 ; idxLevel < this->treeHeight; ++idxLevel){
+            for(long idxD1 = 0 ; idxD1 < this->size1Dim ; ++idxD1){
+                for(long idxD2 = 0 ; idxD2 < this->size1Dim ; ++idxD2){
+                    for(long idxD3 = 0 ; idxD3 < this->size1Dim; ++idxD3){
+                        delete [] this->transferM2L[idxLevel][idxD1][idxD2][idxD3];
+                    }
+                    delete [] this->transferM2L[idxLevel][idxD1][idxD2];
+                }
+                delete [] this->transferM2L[idxLevel][idxD1];
+            }
+            delete [] this->transferM2L[idxLevel];
+        }
+        delete [] this->transferM2L;
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // Utils
+    //////////////////////////////////////////////////////////////////
+
+    // position_2_r_cos_th_sin_th_ph
+    void positionToSphere(const F3DPosition& inVector, Spherical* const outSphere ){
+        const double x2y2 = (inVector.getX() * inVector.getX()) + (inVector.getY() * inVector.getY());
+
+        outSphere->r = FMath::Sqrt( x2y2 + (inVector.getZ() * inVector.getZ()));
+        outSphere->phi = FMath::Atan2(inVector.getY(),inVector.getX());
+        outSphere->cosTheta = inVector.getZ() / outSphere->r; // cos_th = z/r
+        outSphere->sinTheta = FMath::Sqrt(x2y2) / outSphere->r; // sin_th = sqrt(x^2 + y^2)/r
+    }
+
+    // associated_Legendre_function_Fill_complete_array_of_values_for_cos
+    void legendreFunction( const double inCosTheta, const double inSinTheta, double* const outResults ){
+        // l=0:         results[current++] = 1.0; // P_0^0(cosTheta) = 1
+        int idxCurrent = 0;
+        outResults[idxCurrent++] = 1.0;
+
+        // l=1:
+        // Compute P_1^{0} using (3) and store it into results_array:
+        outResults[idxCurrent++] = inCosTheta;
+
+        // Compute P_1^1 using (2 bis) and store it into results_array
+        const double invSinTheta = -inSinTheta; // somx2 => -sinTheta
+        outResults[idxCurrent++] = invSinTheta;
+
+        // l>1:
+        int idxCurrent1m = 1; //pointer on P_{l-1}^m P_1^0
+        int idxCurrent2m = 0; //pointer on P_{l-2}^m P_0^0
+        double fact = 3.0;
+
+        // Remark: p_results_array_l_minus_1_m and p_results_array_l_minus_2_m
+        // just need to be incremented at each iteration.
+        for(int idxl = 2; idxl <= this->LMax ; ++idxl ){
+                for( int idxm = 0; idxm <= idxl - 2 ; ++idxm , ++idxCurrent , ++idxCurrent1m , ++idxCurrent2m ){
+                        // Compute P_l^m, l >= m+2, using (1) and store it into results_array:
+                        outResults[idxCurrent] = (inCosTheta * ( 2 * idxl - 1 ) * outResults[idxCurrent1m] - ( idxl + idxm - 1 )
+                                        * outResults[idxCurrent2m] ) / ( idxl - idxm );
+                }
+                // p_results_array_l_minus_1_m now points on P_{l-1}^{l-1}
+
+                // Compute P_l^{l-1} using (3) and store it into ptrResults:
+                outResults[idxCurrent++] = inCosTheta * ( 2 * idxl - 1 ) * outResults[idxCurrent1m];
+
+                // Compute P_l^l using (2 bis) and store it into results_array:
+                outResults[idxCurrent++] = fact * invSinTheta * outResults[idxCurrent1m];
+
+                fact += 2.0;
+                ++idxCurrent1m;
+        }
+    }
+
+    // spherical_harmonic_Inner
+    void harmonicInner(const Spherical& inSphere, FComplexe* const outResults){
+
+        FComplexe* ptrCosSin = this->cosSin;
+        for(int idxl = 0 , idxlMod4 = 0; idxl <= LMax ; ++idxl, ++idxlMod4, ++ptrCosSin){
+            if(idxlMod4 == 4) idxlMod4 = 0;
+            const double angle = idxl * inSphere.phi + this->PiArrayInner[idxlMod4];
+
+            ptrCosSin->setReal( FMath::Sin(angle + FMath::FPiDiv2) );
+            ptrCosSin->setImag( FMath::Sin(angle) );
+            //std::cout<< idxl << "=" << ptrCosSin->getReal() << "/" << ptrCosSin->getImag() << " (" << idxl << "/" << inSphere.phi << "/" << PiArray[lMod4] << ")\n";
+        }
+
+        legendreFunction(inSphere.cosTheta, inSphere.sinTheta, this->legendre);
+        //printf("FMB_Info_M2L_exp_size=%d\n",FMB_Info_M2L_exp_size);
+        //for(int temp = 0 ; temp < FMB_Info_M2L_exp_size ; ++temp){
+        //    printf("%f\n",this->legendre[temp]);
+        //}
+
+        FComplexe* currentResult = outResults;
+        int idxLegendre = 0;//ptr_associated_Legendre_function_Array
+        int idxSphereHarmoCoef = 0;
+        double idxRl = 1.0 ;
+
+        for(int idxl = 0; idxl <= this->LMax ; ++idxl, idxRl *= inSphere.r){
+            for(int idxm = 0 ; idxm <= idxl ; ++idxm, ++currentResult, ++idxSphereHarmoCoef, ++idxLegendre){
+                const double magnitude = this->sphereHarmoInnerCoef[idxSphereHarmoCoef] * idxRl * legendre[idxLegendre];
+                currentResult->setReal( magnitude * this->cosSin[idxm].getReal() );
+                currentResult->setImag( magnitude * this->cosSin[idxm].getImag() );
+                //printf("magnitude=%f idxRl=%f sphereHarmoInnerCoef=%f real=%f imag=%f\n",magnitude,idxRl,this->sphereHarmoInnerCoef[idxSphereHarmoCoef],currentResult->getReal(),currentResult->getImag());
+            }
+        }
+
+    }
+    // spherical_harmonic_Outer
+    void harmonicOuter(const Spherical& inSphere, FComplexe* const outResults){
+
+        FComplexe* ptrCosSin = this->cosSin;
+        for(int idxl = 0, idxlMod4 = 0; idxl <= LMax ; ++idxl, ++idxlMod4, ++ptrCosSin){
+            if(idxlMod4 == 4) idxlMod4 = 0;
+            const double angle = idxl * inSphere.phi + this->PiArrayOuter[idxlMod4];
+
+            ptrCosSin->setReal( FMath::Sin(angle + FMath::FPiDiv2) );
+            ptrCosSin->setImag( FMath::Sin(angle) );
+
+            //printf("l=%d \t inSphere.phi=%f \t this->PiArrayOuter[idxlMod4]=%f \t angle=%f \t FMath::Sin(angle + FMath::FPiDiv2)=%f \t FMath::Sin(angle)=%f\n",
+            //        idxl, inSphere.phi, this->PiArrayOuter[idxlMod4], angle, FMath::Sin(angle + FMath::FPiDiv2) , FMath::Sin(angle));
+        }
+
+        legendreFunction(inSphere.cosTheta, inSphere.sinTheta, this->legendre);
+
+        int idxLegendre = 0;
+        FComplexe* currentResult = outResults;
+
+        const double invR = 1/inSphere.r;
+        double idxRl1 = invR;
+        for(int idxl = 0 ; idxl <= this->LMax ; ++idxl, idxRl1 *= invR){
+            for(int idxm = 0 ; idxm <= idxl ; ++idxm, ++currentResult, ++idxLegendre){
+                const double magnitude = this->sphereHarmoOuterCoef[idxl-idxm] * idxRl1 * this->legendre[idxLegendre];
+                currentResult->setReal( magnitude * this->cosSin[idxm].getReal() );
+                currentResult->setImag( magnitude * this->cosSin[idxm].getImag() );
+                //printf("l=%d\t m=%d\t idxRl1=%f\t magnitude=%f\n",idxl,idxm,idxRl1,magnitude);
+                //printf("l=%d\t m=%d\t this->cosSin[idxm].getReal()=%f\t this->cosSin[idxm].getImag()=%f\n",
+                //       idxl,idxm,this->cosSin[idxm].getReal(),this->cosSin[idxm].getImag());
+            }
+        }
+    }
+
+    /** spherical_harmonic_Inner_and_theta_derivated
+        * Returns the value of the partial derivative of the spherical harmonic
+        *relative to theta. We have for all m such that -(l-1) <= m <= l-1 :
+        *
+        *(d H_l^m(theta, phi))/(d theta)
+        *= (-1)^m sqrt((l-|m|)!/(l+|m|)!) (d P_l^{|m|}(cos theta))/(d theta) e^{i.m.phi}
+        *= (-1)^m sqrt((l-|m|)!/(l+|m|)!) 1/sqrt{1-cos^2 theta} [l cos theta P_l^{|m|}(cos theta) - (l+|m|) P_{l-1}^{|m|}(cos theta) ] e^{i.m.phi}
+        *Since theta is in the range [0, Pi], we have: sin theta > 0 and therefore
+        *sqrt{1-cos^2 theta} = sin theta. Thus:
+        *
+        *(d H_l^m(theta, phi))/(d theta)
+        *= (-1)^m sqrt((l-|m|)!/(l+|m|)!) 1/(sin theta) [l cos theta P_l^{|m|}(cos theta) - (l+|m|) P_{l-1}^{|m|}(cos theta) ] e^{i.m.phi}
+        *For |m|=l, we have~:
+        *(d H_l^l(theta, phi))/(d theta)
+        *= (-1)^m sqrt(1/(2l)!) 1/(sin theta) [l cos theta P_l^l(cos theta) ] e^{i.m.phi}
+        *
+        *Remark: for 0<m<=l:
+        *(d H_l^{-m}(theta, phi))/(d theta) = [(d H_l^{-m}(theta, phi))/(d theta)]*
+        *
+        *
+        *
+        *Therefore, we have for (d Inner_l^m(r, theta, phi))/(d theta):
+        *
+        *|m|<l: (d Inner_l^m(r, theta, phi))/(d theta) =
+        *(i^m (-1)^l / (l+|m|)!) 1/(sin theta) [l cos theta P_l^{|m|}(cos theta) - (l+|m|) P_{l-1}^{|m|}(cos theta) ] e^{i.m.phi} r^l
+        *|m|=l: (d Inner_l^m(r, theta, phi))/(d theta) =
+        *(i^m (-1)^l / (l+|m|)!) 1/(sin theta) [l cos theta P_l^l(cos theta) ] e^{i.m.phi} r^l
+        *
+        *
+      */
+    void harmonicInnerThetaDerivated(
+                         const Spherical& inSphere,
+                         FComplexe * results_array,
+                         FComplexe * theta_derivated_results_array
+                         ){
+        FComplexe *p_term = results_array;
+        FComplexe *p_theta_derivated_term = theta_derivated_results_array;
+        double *p_spherical_harmonic_Inner_coefficients_array = sphereHarmoInnerCoef;
+        double *ptr_associated_Legendre_function_Array = legendre;
+        double *start_ptr_associated_Legendre_function_Array = ptr_associated_Legendre_function_Array;
+
+
+        // Initialization of precomputed_cos_and_sin_array:
+        for(int idxm = 0 , idxmMod4 = 0; idxm <= FMB_Info_P ; ++idxm, ++idxmMod4){
+            if(idxmMod4 == 4) idxmMod4 = 0;
+            const double angle = idxm*inSphere.phi + PiArrayInner[idxmMod4];
+            (cosSin + idxm)->setReal(FMath::Sin(angle + M_PI_2));
+            (cosSin + idxm)->setImag(FMath::Sin(angle));
+        }
+
+        // Initialization of associated_Legendre_function_Array:
+        legendreFunction( inSphere.cosTheta, inSphere.sinTheta, this->legendre);
+
+        // r^l
+        double r_l = 1.0;
+        for (int l = 0 ; l <= FMB_Info_P ; ++l, r_l *= inSphere.r){
+            double magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * (*ptr_associated_Legendre_function_Array);
+            // m<l:
+            int m = 0;
+            for(; m < l ; ++m, ++p_term, ++p_theta_derivated_term, ++p_spherical_harmonic_Inner_coefficients_array, ++ptr_associated_Legendre_function_Array){
+                // Computation of Inner_l^m(r, theta, phi):
+                p_term->setReal( magnitude * (cosSin + m)->getReal());
+                p_term->setImag( magnitude * (cosSin + m)->getImag());
+                // Computation of {\partial Inner_l^m(r, theta, phi)}/{\partial theta}:
+                magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * ((l*inSphere.cosTheta*(*ptr_associated_Legendre_function_Array)
+                                        - (l+m)*(*(start_ptr_associated_Legendre_function_Array + expansion_Redirection_array_for_j[l-1] + m))) / inSphere.sinTheta);
+                p_theta_derivated_term->setReal(magnitude * (cosSin + m)->getReal());
+                p_theta_derivated_term->setImag(magnitude * (cosSin + m)->getImag());
+            }
+
+            // m=l:
+            // Computation of Inner_m^m(r, theta, phi):
+            magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * (*ptr_associated_Legendre_function_Array);
+            p_term->setReal(magnitude * (cosSin + m)->getReal());
+            p_term->setImag(magnitude * (cosSin + m)->getImag());
+            // Computation of {\partial Inner_m^m(r, theta, phi)}/{\partial theta}:
+            magnitude = (*p_spherical_harmonic_Inner_coefficients_array) * r_l * (m * inSphere.cosTheta * (*ptr_associated_Legendre_function_Array) / inSphere.sinTheta);
+            p_theta_derivated_term->setReal(magnitude * (cosSin + m)->getReal());
+            p_theta_derivated_term->setImag(magnitude * (cosSin + m)->getImag());
+
+            ++p_term;
+            ++p_theta_derivated_term;
+            ++p_spherical_harmonic_Inner_coefficients_array;
+            ++ptr_associated_Legendre_function_Array;
+        }
+    }
+
+    //[fmb] ff_matrix_Convert_exp_2_transfer_M2L_matrix
+    /*[Blas] void expffmatrix(const FComplexe* transfer_exp, FComplexe* const ff_transfer_matrix){
+        FComplexe *p_ff_transfer_matrix = ff_transfer_matrix;
+
+        for( int M = 0; M <= this->FMB_Info_P ; ++M ){
+            for(int  m = 0; m <= M ; ++m ){
+                for(int  N = 0; N <= FMB_Info_P ; ++N ){
+                    for(int n = 0; n <= 2 * N ; ++n , ++p_ff_transfer_matrix ){
+                        const int k = N - n - m;
+                        if(k < 0){
+                            const int pow_of_minus_1_k = ((k%2) ? -1 : 1);
+                            p_ff_transfer_matrix->setReal(pow_of_minus_1_k  * transfer_exp[ expansion_Redirection_array_for_j[M + N] - k].getReal());
+                            p_ff_transfer_matrix->setImag((-pow_of_minus_1_k) * transfer_exp[ expansion_Redirection_array_for_j[M + N] - k].getImag());
+                        }
+                        else{
+                            int temp = expansion_Redirection_array_for_j[M + N];
+                            *p_ff_transfer_matrix = transfer_exp[ expansion_Redirection_array_for_j[M + N] + k];
+                        }
+                    }
+                }
+            }
+        }
+    }*/
+
+    //////////////////////////////////////////////////////////////////
+    // Precompute
+    //////////////////////////////////////////////////////////////////
+
+    // transfer_M2M_Precompute_all_levels
+    // transfer_L2L_Precompute_all_levels
+    void precomputeM2M(){
+        double treeWidthAtLevel = this->treeWidthAtRoot/2;
+
+        for(int idxLevel = 0 ; idxLevel < this->treeHeight ; ++idxLevel ){
+            const F3DPosition father(treeWidthAtLevel,treeWidthAtLevel,treeWidthAtLevel);
+            treeWidthAtLevel /= 2;
+
+            //std::cout << "[precomputeM2M]treeWidthAtLevel=" << treeWidthAtLevel << "\n";
+            //printf("\tidxLevel=%d\tFather.x=%f\tFather.y=%f\tFather.z=%f\n",idxLevel,father.getX(),father.getY(),father.getZ());
+
+            for(int idxChild = 0 ; idxChild < 8 ; ++idxChild ){
+                FTreeCoordinate childBox;
+                childBox.setPositionFromMorton(idxChild,1);
+
+                const F3DPosition M2MVector (
+                        father.getX() - (treeWidthAtLevel * (1 + (childBox.getX() * 2))),
+                        father.getY() - (treeWidthAtLevel * (1 + (childBox.getY() * 2))),
+                        father.getZ() - (treeWidthAtLevel * (1 + (childBox.getZ() * 2)))
+                );
+                Spherical sphericalM2M;
+                positionToSphere(M2MVector,&sphericalM2M);
+                harmonicInner(sphericalM2M,this->transitionM2M[idxLevel][idxChild]);
+
+                const F3DPosition L2LVector (
+                        (treeWidthAtLevel * (1 + (childBox.getX() * 2))) - father.getX(),
+                        (treeWidthAtLevel * (1 + (childBox.getY() * 2))) - father.getY(),
+                        (treeWidthAtLevel * (1 + (childBox.getZ() * 2))) - father.getZ()
+                );
+                Spherical sphericalL2L;
+                positionToSphere(L2LVector,&sphericalL2L);
+                harmonicInner(sphericalL2L,this->transitionL2L[idxLevel][idxChild]);
+
+                //std::cout << "[M2M_vector]" << idxLevel << "/" << idxChild << " = " << M2MVector.getX() << "/" << M2MVector.getY() << "/" << M2MVector.getZ() << "\n";
+                //std::cout << "[M2M_vectorSpherical]" << idxLevel << "/" << idxChild << " = " << sphericalM2M.r << "/" << sphericalM2M.cosTheta << "/" << sphericalM2M.sinTheta << "/" << sphericalM2M.phi << "\n";
+                //for(int idxExpSize = 0 ; idxExpSize < FMB_Info_exp_size ; ++idxExpSize){
+                    //std::cout << "transitionL2L[" << idxLevel << "][" << idxChild << "][" << idxExpSize << "]=" << this->transitionL2L[idxLevel][idxChild][idxExpSize].getReal()<<"/"<<this->transitionL2L[idxLevel][idxChild][idxExpSize].getImag()<< "\n";
+                    //std::cout << "transitionM2M[" << idxLevel << "][" << idxChild << "][" << idxExpSize << "]=" << this->transitionM2M[idxLevel][idxChild][idxExpSize].getReal()<<"/"<<this->transitionM2M[idxLevel][idxChild][idxExpSize].getImag()<< "\n";
+                //}
+            }
+        }
+
+    }
+
+
+    // transfer_M2L_Precompute_all_levels
+    void precomputeM2L(){
+        //[Blas] FComplexe tempComplexe[FMB_Info_M2L_exp_size];
+        //printf("FMB_Info.M2L_exp_size = %d\n",FMB_Info_M2L_exp_size);
+
+        double treeWidthAtLevel = this->treeWidthAtRoot;
+        for(int idxLevel = 0 ; idxLevel < this->treeHeight ; ++idxLevel ){
+            //printf("level = %d \t width = %lf\n",idxLevel,treeWidthAtLevel);
+            for( int idxd1 = 0; idxd1 < this->size1Dim ; ++idxd1 ){
+
+                for( int idxd2 = 0; idxd2 < this->size1Dim ; ++idxd2 ){
+
+                    for( int idxd3 = 0; idxd3 < this->size1Dim ; ++idxd3 ){
+                        const long x = idxd1 - this->halphSize1Dim;
+                        const long y = idxd2 - this->halphSize1Dim;
+                        const long z = idxd3 - this->halphSize1Dim;
+
+                        //printf("x=%ld \t y=%ld \t z=%ld\n",x,y,z);
+
+                        if( ( x*x + y*y + z*z ) >= ( 3*FMB_Info_ws*FMB_Info_ws + 0.1 ) ){
+                            const F3DPosition relativePos( x*treeWidthAtLevel , y*treeWidthAtLevel , z*treeWidthAtLevel );                            
+
+                            Spherical spherical;
+                            positionToSphere(relativePos,&spherical);
+                            // Not blas so
+                            //printf("transferM2L[%d][%d][%d][%d]\n", idxLevel, idxd1, idxd2, idxd3);
+                            harmonicOuter(spherical,this->transferM2L[idxLevel][idxd1][idxd2][idxd3]);
+                            //for(int idxTemp = 0 ; idxTemp < this->FMB_Info_M2L_exp_size ; ++idxTemp){
+                            //    printf("transferM2L[%d][%d][%d][%d][%d]=%f/%f\n", idxLevel, idxd1, idxd2, idxd3, idxTemp, this->transferM2L[idxLevel][idxd1][idxd2][idxd3][idxTemp].getReal(),this->transferM2L[idxLevel][idxd1][idxd2][idxd3][idxTemp].getImag());
+                            //}
+
+                            //[Blas] harmonicOuter(spherical,tempComplexe);
+                            //[Blas] ff_matrix_Convert_exp_2_transfer_M2L_matrix
+                            //[Blas] expffmatrix( tempComplexe , this->transferM2L[idxLevel][idxd1][idxd2][idxd3] );
+                        }
+
+                    }
+                }
+            }
+            treeWidthAtLevel /= 2;
+        }
+    }
+
+    void buildPrecompute(){
+        expansion_Redirection_array_for_j_Initialize();
+        sphericalHarmonicInitialize();
+        transferAllocate();
+
+        precomputeM2M();
+        precomputeM2L();
+    }
+
+public:
+    FFmbKernels(const int inTreeHeight, const double inTreeWidth)
+        : treeHeight(inTreeHeight), treeWidthAtRoot(inTreeWidth),
+          transitionM2M(0), transitionL2L(0), potential_sum(0){
+        buildPrecompute();
+    }
+
+    /** Default destructor */
+    virtual ~FFmbKernels(){
+        transferDeallocate();
+    }
+
+    F3DPosition getForcesSum() const {
+        return force_sum;
+    }
+
+    double getPotential() const{
+        return potential_sum;
+    }
+
+    /////////////////////////////////////////////////////////////////////////////////
+    //    Upward
+    /////////////////////////////////////////////////////////////////////////////////
+
+    /** OK!
+    * expansion_P2M_add
+    * Multipole expansion with m charges q_i in Q_i=(rho_i, alpha_i, beta_i)
+    *whose relative coordinates according to *p_center are:
+    *Q_i - *p_center = (rho'_i, alpha'_i, beta'_i);
+    *
+    *For j=0..P, k=-j..j, we have:
+    *
+    *M_j^k = (-1)^j { sum{i=1..m} q_i Inner_j^k(rho'_i, alpha'_i, beta'_i) }
+    *
+    *However the extern loop is over the bodies (i=1..m) in our code and as an
+    *intern loop we have: j=0..P, k=-j..j
+    *
+    *and the potential is then given by:
+    *
+    * Phi(x) = sum_{n=0}^{+} sum_{m=-n}^{n} M_n^m O_n^{-m} (x - *p_center)
+    *
+    */
+    void P2M(CellClass* const inPole, FList<ParticuleClass*>* const inParticules) {
+
+        for(typename FList<ParticuleClass*>::BasicIterator iterParticule(*inParticules);
+                                iterParticule.isValide() ; iterParticule.progress()){
+
+            Spherical spherical;
+            positionToSphere(iterParticule.value()->getPosition() - inPole->getPosition(), &spherical);
+
+            //std::cout << "Working on part " << iterParticule.value()->getValue() << "\n";
+            F3DPosition tempPos = iterParticule.value()->getPosition() - inPole->getPosition();
+            //ok printf("\tpos_rel.x=%f\tpos_rel.y=%f\tpos_rel.z=%f\n",tempPos.getX(),tempPos.getY(),tempPos.getZ());
+            //ok printf("\tp_center.x=%f\tp_center.y=%f\tp_center.z=%f\n",inPole->getPosition().getX(),inPole->getPosition().getY(),inPole->getPosition().getZ());
+            //ok printf("\tbody.x=%f\tbody.y=%f\tbody.z=%f\n",iterParticule.value()->getPosition().getX(),iterParticule.value()->getPosition().getY(),iterParticule.value()->getPosition().getZ());
+
+            harmonicInner(spherical,current_thread_Y);
+
+            //ok printf("\tr=%f\tcos_theta=%f\tsin_theta=%f\tphi=%f\n",spherical.r,spherical.cosTheta,spherical.sinTheta,spherical.phi);
+
+            FComplexe* p_exp_term = inPole->getMultipole();
+            FComplexe* p_Y_term = current_thread_Y;
+            double pow_of_minus_1_j = 1.0;//(-1)^j
+            const double valueParticule = iterParticule.value()->getValue();
+
+            for(int j = 0 ; j <= FMB_Info_P ; ++j, pow_of_minus_1_j = -pow_of_minus_1_j ){
+                for(int k = 0 ; k <= j ; ++k, ++p_Y_term, ++p_exp_term){
+                    p_Y_term->mulRealAndImag( valueParticule * pow_of_minus_1_j );
+                    (*p_exp_term) += (*p_Y_term);
+                    //printf("\tj=%d\tk=%d\tp_exp_term.real=%f\tp_exp_term.imag=%f\tp_Y_term.real=%f\tp_Y_term.imag=%f\tpow_of_minus_1_j=%f\n", j,k,(*p_exp_term).getReal(),(*p_exp_term).getImag(),(*p_Y_term).getReal(),(*p_Y_term).getImag(),pow_of_minus_1_j);
+                }
+            }
+        }
+    }
+
+    /**
+    *-----------------------------------
+    *octree_Upward_pass_internal_cell
+    *expansion_M2M_add
+    *-----------------------------------
+    *We compute the translation of multipole_exp_src from *p_center_of_exp_src to
+    *p_center_of_exp_target, and add the result to multipole_exp_target.
+    *
+    * O_n^l (with n=0..P, l=-n..n) being the former multipole expansion terms
+    * (whose center is *p_center_of_multipole_exp_src) we have for the new multipole
+    * expansion terms (whose center is *p_center_of_multipole_exp_target):
+
+    * M_j^k = sum{n=0..j}
+    * sum{l=-n..n, |k-l|<=j-n}
+    * O_n^l Inner_{j-n}^{k-l}(rho, alpha, beta)
+    *
+    * where (rho, alpha, beta) are the spherical coordinates of the vector :
+    * p_center_of_multipole_exp_target - *p_center_of_multipole_exp_src
+    *
+    * Warning: if j-n < |k-l| we do nothing.
+     */
+    void M2M(CellClass* const inPole, CellClass** const inChild, const int inLevel) {
+
+        // We do NOT have: for(l=n-j+k; l<=j-n+k ;++l){} <=> for(l=-n; l<=n ;++l){if (j-n >= abs(k-l)){}}
+        //     But we have:  for(k=MAX(0,n-j+l); k<=j-n+l; ++k){} <=> for(k=0; k<=j; ++k){if (j-n >= abs(k-l)){}}
+        //     (This is not the same as in L2L since the range of values of k is not the same, compared to "n-j" or "j-n".)
+        //     Therefore the loops over n and l are the outmost ones and
+        //     we invert the loop over j with the summation with n:
+        //     for{j=0..P} sum_{n=0}^j <-> sum_{n=0}^P for{j=n..P}
+        FComplexe* const multipole_exp_target = inPole->getMultipole();
+
+        for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){
+            if(!inChild[idxChild]) continue;
+            //printf("\tChild %d\n",idxChild);
+
+            const FComplexe* const multipole_exp_src = inChild[idxChild]->getMultipole();
+
+            const FComplexe* const M2M_transfer = transitionM2M[inLevel][idxChild];
+
+            for(int n = 0 ; n <= FMB_Info_P ; ++n ){
+                // l<0 // (-1)^l
+                double pow_of_minus_1_for_l = ( n % 2 ? -1 : 1);
+
+                // O_n^l : here points on the source multipole expansion term of degree n and order |l|
+                const FComplexe* p_src_exp_term = multipole_exp_src + expansion_Redirection_array_for_j[n]+n;
+                //printf("\t[p_src_exp_term] expansion_Redirection_array_for_j[n]=%d\tn=%d\n",expansion_Redirection_array_for_j[n],n);
+
+                int l = -n;
+                for(; l<0 ; ++l, --p_src_exp_term, pow_of_minus_1_for_l = -pow_of_minus_1_for_l){
+
+                    for(int j = n ; j<= FMB_Info_P ; ++j ){
+                        // M_j^k
+                        FComplexe *p_target_exp_term = multipole_exp_target + expansion_Redirection_array_for_j[j];
+                        //printf("\t[p_target_exp_term] expansion_Redirection_array_for_j[j]=%d\n",expansion_Redirection_array_for_j[j]);
+                        // Inner_{j-n}^{k-l} : here points on the M2M transfer function/expansion term of degree n-j and order |k-l|
+                        const FComplexe *p_Inner_term= M2M_transfer + expansion_Redirection_array_for_j[j-n]-l /* k==0 */;
+                        //printf("\t[p_Inner_term] expansion_Redirection_array_for_j[j-n]=%d\tl=%d\n",expansion_Redirection_array_for_j[j-n],-l);
+
+                        // since n-j+l<0
+                        for(int k=0 ; k <= (j-n+l) ; ++k, ++p_target_exp_term, ++p_Inner_term){ // l<0 && k>=0 => k-l>0
+                            p_target_exp_term->incReal( pow_of_minus_1_for_l *
+                                                        ((p_src_exp_term->getReal() * p_Inner_term->getReal()) +
+                                                         (p_src_exp_term->getImag() * p_Inner_term->getImag())));
+                            p_target_exp_term->incImag( pow_of_minus_1_for_l *
+                                                        ((p_src_exp_term->getReal() * p_Inner_term->getImag()) -
+                                                         (p_src_exp_term->getImag() * p_Inner_term->getReal())));
+
+                            //printf("\tp_src_exp_term->getReal()=%f\tp_src_exp_term->getImag()=%f\n", p_src_exp_term->getReal(),p_src_exp_term->getImag());
+                            //printf("\tp_Inner_term->getReal()=%f\tp_Inner_term->getImag()=%f\n", p_Inner_term->getReal(),p_Inner_term->getImag());
+                            //printf("\tn[%d]l[%d]j[%d]k[%d] = %f / %f\n",n,l,j,k,p_target_exp_term->getReal(),p_target_exp_term->getImag());
+
+                        } // for k
+                    } // for j
+                } // for l
+
+                // l>=0
+                for(; l <= n ; ++l, ++p_src_exp_term, pow_of_minus_1_for_l = -pow_of_minus_1_for_l){
+
+                    for( int j=n ; j <= FMB_Info_P ; ++j ){
+                        // (-1)^k
+                        double pow_of_minus_1_for_k = ( FMath::Max(0,n-j+l) %2 ? -1 : 1 );
+                        // M_j^k
+                        FComplexe *p_target_exp_term = multipole_exp_target + expansion_Redirection_array_for_j[j] + FMath::Max(0,n-j+l);
+                        // Inner_{j-n}^{k-l} : here points on the M2M transfer function/expansion term of degree n-j and order |k-l|
+                        const FComplexe *p_Inner_term = M2M_transfer + expansion_Redirection_array_for_j[j-n] + l - FMath::Max(0,n-j+l);// -(k-l)
+
+                        int k = FMath::Max(0,n-j+l);
+                        for(; k <= (j-n+l) && (k-l) < 0 ; ++k, ++p_target_exp_term, --p_Inner_term, pow_of_minus_1_for_k = -pow_of_minus_1_for_k){ /* l>=0 && k-l<0 */
+                            p_target_exp_term->incReal( pow_of_minus_1_for_k * pow_of_minus_1_for_l *
+                                                        ((p_src_exp_term->getReal() * p_Inner_term->getReal()) +
+                                                         (p_src_exp_term->getImag() * p_Inner_term->getImag())));
+                            p_target_exp_term->incImag(pow_of_minus_1_for_k * pow_of_minus_1_for_l *
+                                                       ((p_src_exp_term->getImag() * p_Inner_term->getReal()) -
+                                                        (p_src_exp_term->getReal() * p_Inner_term->getImag())));
+                            //printf("\tn[%d]l[%d]j[%d]k[%d] = %f / %f\n",n,l,j,k,p_target_exp_term->getReal(),p_target_exp_term->getImag());
+
+                        } // for k
+
+                        for(; k <= (j - n + l) ; ++k, ++p_target_exp_term, ++p_Inner_term){ // l>=0 && k-l>=0
+                            p_target_exp_term->incReal(
+                                    (p_src_exp_term->getReal() * p_Inner_term->getReal()) -
+                                    (p_src_exp_term->getImag() * p_Inner_term->getImag()));
+                            p_target_exp_term->incImag(
+                                    (p_src_exp_term->getImag() * p_Inner_term->getReal()) +
+                                    (p_src_exp_term->getReal() * p_Inner_term->getImag()));
+                            //printf("\tn[%d]l[%d]j[%d]k[%d] = %f / %f\n",n,l,j,k,p_target_exp_term->getReal(),p_target_exp_term->getImag());
+
+                        } // for k
+                    } // for j
+                } // for l
+            } // for n
+        }
+    }
+
+    /////////////////////////////////////////////////////////////////////////////////
+    //    M2L
+    /////////////////////////////////////////////////////////////////////////////////
+    /**
+    *------------------
+    * expansion_M2L_add
+    *-------------------
+    *We compute the conversion of multipole_exp_src in *p_center_of_exp_src to
+    *a local expansion in *p_center_of_exp_target, and add the result to local_exp_target.
+    *
+    *O_n^l (with n=0..P, l=-n..n) being the former multipole expansion terms
+    *(whose center is *p_center_of_multipole_exp_src) we have for the new local
+    *expansion terms (whose center is *p_center_of_local_exp_target):
+    *
+    *L_j^k = sum{n=0..+}
+    *sum{l=-n..n}
+    *O_n^l Outer_{j+n}^{-k-l}(rho, alpha, beta)
+    *
+    *where (rho, alpha, beta) are the spherical coordinates of the vector :
+    *p_center_of_local_exp_src - *p_center_of_multipole_exp_target
+    *
+    *Remark: here we have always j+n >= |-k-l|
+      *
+      */
+    void M2L(CellClass* const pole, CellClass** const distantNeighbors, const int size, const int inLevel) {
+        FTreeCoordinate coordCenter;
+        coordCenter.setPositionFromMorton(pole->getMortonIndex(),inLevel);
+
+        bool FMB_Info_up_to_P_in_M2L = true;
+
+        for(int idxSize = 0 ; idxSize < size ; ++idxSize){
+            FTreeCoordinate coordNeighbors;
+            coordNeighbors.setPositionFromMorton(distantNeighbors[idxSize]->getMortonIndex(),inLevel);
+
+            //printf("\tidxSize = %d\tleve = %d\tMorton = %lld\n",idxSize,inLevel,distantNeighbors[idxSize]->getMortonIndex());
+
+            const FComplexe* const M2L_transfer = transferM2L[inLevel]
+                                      [6-(coordNeighbors.getX()+halphSize1Dim-coordCenter.getX())]
+                                      [6-(coordNeighbors.getY()+halphSize1Dim-coordCenter.getY())]
+                                      [6-(coordNeighbors.getZ()+halphSize1Dim-coordCenter.getZ())];
+            /*printf("level = %d\tx=%ld\ty=%ld\tz=%ld\n", inLevel,
+                   6-(coordNeighbors.getX()+halphSize1Dim-coordCenter.getX()),
+                   6-(coordNeighbors.getY()+halphSize1Dim-coordCenter.getY()),
+                   6-(coordNeighbors.getZ()+halphSize1Dim-coordCenter.getZ()));*/
+            /*printf("M2L_transfer[0]= %f/%f\n",M2L_transfer->getReal(),M2L_transfer->getImag());
+            printf("M2L_transfer[1]= %f/%f\n",M2L_transfer[1].getReal(),M2L_transfer[1].getImag());
+            printf("M2L_transfer[2]= %f/%f\n",M2L_transfer[2].getReal(),M2L_transfer[2].getImag());*/
+            const FComplexe* const multipole_exp_src = distantNeighbors[idxSize]->getMultipole();
+            // L_j^k
+            FComplexe* p_target_exp_term = pole->getLocal();
+            int start_for_j = 0;
+            //#if defined (_FORCES_) && !defined(_ENERGY_)
+            // See FMB.c:
+            if (FMB_Info_up_to_P_in_M2L){
+                start_for_j = 1;
+                ++p_target_exp_term;
+            }
+            //#endif // #if defined (_FORCES_) && !defined(_ENERGY_)
+
+            //    HPMSTART(51, "M2L computation (loops)");
+            for (int j = start_for_j ; j <= FMB_Info_P ; ++j){
+
+                int stop_for_n = FMB_Info_P;
+                if (FMB_Info_up_to_P_in_M2L){
+                    stop_for_n = FMB_Info_P - j;
+                }
+
+                // (-1)^k
+                double pow_of_minus_1_for_k = 1.0;
+                for (int k = 0 ; k <= j ; ++k, pow_of_minus_1_for_k = -pow_of_minus_1_for_k, ++p_target_exp_term){
+
+                    // (-1)^n
+                    double pow_of_minus_1_for_n = 1.0;
+                    for (int n = 0 ; n <= stop_for_n ; ++n, pow_of_minus_1_for_n = -pow_of_minus_1_for_n){
+
+                        // O_n^l : here points on the source multipole expansion term of degree n and order |l|
+                        const FComplexe *p_src_exp_term = multipole_exp_src + expansion_Redirection_array_for_j[n] + n;
+                        // Outer_{j+n}^{-k-l} : here points on the M2L transfer function/expansion term of degree j+n and order |-k-l|
+                        const FComplexe *p_Outer_term = M2L_transfer + expansion_Redirection_array_for_j[n+j] + k+n;
+                        //printf("expansion_Get_p_term(M2L_transfer, n+j, k+n)-M2L_transfer = %d \t(n=%d)\n",
+                        //       p_Outer_term-M2L_transfer , n );
+                        //printf("TRUC = %d\n",expansion_Redirection_array_for_j[n+j] + k+n);
+                        double pow_of_minus_1_for_l = pow_of_minus_1_for_n; // (-1)^l
+                        // We start with l=n (and not l=-n) so that we always set p_Outer_term to a correct value in the first loop.
+                        int l=n;
+                        for ( ; l>0 ; --l, pow_of_minus_1_for_l = -pow_of_minus_1_for_l, --p_src_exp_term, --p_Outer_term){ // we have -k-l<0 and l>0
+                            p_target_exp_term->incReal( pow_of_minus_1_for_l * pow_of_minus_1_for_k *
+                                                        ((p_src_exp_term->getReal() * p_Outer_term->getReal()) +
+                                                         (p_src_exp_term->getImag() * p_Outer_term->getImag())));
+                            p_target_exp_term->incImag( pow_of_minus_1_for_l * pow_of_minus_1_for_k *
+                                                        ((p_src_exp_term->getImag() * p_Outer_term->getReal()) -
+                                                         (p_src_exp_term->getReal() * p_Outer_term->getImag())));
+                            //printf("\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n",
+                            //                               p_target_exp_term->getReal(),p_target_exp_term->getImag());
+                            //printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n",
+                            //                               p_src_exp_term->getReal(),p_src_exp_term->getImag());
+                            //printf("p_Outer_term-M2L_transfer = %d\n",
+                            //                               p_Outer_term-M2L_transfer);
+                            //printf("\t p_Outer_term->real = %f \t p_Outer_term->imag = %f \n",
+                            //                               p_Outer_term->getReal(),p_Outer_term->getImag());
+                        }
+
+                        for (; l>=-n && -k-l<0 ; --l, pow_of_minus_1_for_l = -pow_of_minus_1_for_l, ++p_src_exp_term, --p_Outer_term){ // we have -k-l<0 and l<=0
+                            p_target_exp_term->incReal( pow_of_minus_1_for_k *
+                                                        ((p_src_exp_term->getReal() * p_Outer_term->getReal()) -
+                                                         (p_src_exp_term->getImag() * p_Outer_term->getImag())));
+                            p_target_exp_term->decImag(  pow_of_minus_1_for_k *
+                                                         ((p_src_exp_term->getImag() * p_Outer_term->getReal()) +
+                                                          (p_src_exp_term->getReal() * p_Outer_term->getImag())));
+                        }
+
+                        for (; l>=-n; --l, pow_of_minus_1_for_l = -pow_of_minus_1_for_l, ++p_src_exp_term, ++p_Outer_term){ // we have -k-l>=0 and l<=0
+                            p_target_exp_term->incReal( pow_of_minus_1_for_l *
+                                                        ((p_src_exp_term->getReal() * p_Outer_term->getReal()) +
+                                                         (p_src_exp_term->getImag() * p_Outer_term->getImag())));
+                            p_target_exp_term->incImag( pow_of_minus_1_for_l *
+                                                        ((p_src_exp_term->getReal() * p_Outer_term->getImag()) -
+                                                         (p_src_exp_term->getImag() * p_Outer_term->getReal())));
+                        }
+                        //printf("\tj=%d\tk=%d\tn=%d\tl=%d\n",j,k,n,l);
+                        //printf("\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n",
+                        //       p_target_exp_term->getReal(),p_target_exp_term->getImag());
+                    }
+                }
+            }
+        }
+    }
+
+    /////////////////////////////////////////////////////////////////////////////////
+    //    Downard
+    /////////////////////////////////////////////////////////////////////////////////
+
+    /**
+      *We compute the shift of local_exp_src from *p_center_of_exp_src to
+      *p_center_of_exp_target, and set the result to local_exp_target.
+      *
+      *O_n^l (with n=0..P, l=-n..n) being the former local expansion terms
+      *(whose center is *p_center_of_exp_src) we have for the new local
+      *expansion terms (whose center is *p_center_of_exp_target):
+      *
+      *L_j^k = sum{n=j..P}
+      *sum{l=-n..n}
+      *O_n^l Inner_{n-j}^{l-k}(rho, alpha, beta)
+      *
+      *where (rho, alpha, beta) are the spherical coordinates of the vector :
+      *p_center_of_exp_target - *p_center_of_exp_src
+      *
+      *Warning: if |l-k| > n-j, we do nothing.
+      */
+    void L2L(CellClass* const pole, CellClass** const child, const int inLevel) {
+
+        for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){
+            // if no child at this position
+            if(!child[idxChild]) continue;
+
+            const FComplexe* const L2L_tranfer = transitionL2L[inLevel][idxChild];
+            const FComplexe* const local_exp_src = pole->getLocal();
+            FComplexe* const local_exp_target = child[idxChild]->getLocal();
+
+            /*printf("Level %d\n", inLevel);
+            printf("Father morton %lld\n", pole->getMortonIndex());
+            printf("Child morton %lld\n", child[idxChild]->getMortonIndex());*/
+
+            // L_j^k
+            FComplexe* p_target_exp_term = local_exp_target;
+            for (int j=0 ; j<= FMB_Info_P ; ++j){
+                // (-1)^k
+                double pow_of_minus_1_for_k = 1.0;
+                for (int k=0 ; k <= j ; ++k, pow_of_minus_1_for_k = -pow_of_minus_1_for_k, ++p_target_exp_term){
+                    for (int n=j; n<=FMB_Info_P;++n){
+                        // O_n^l : here points on the source multipole expansion term of degree n and order |l|
+                        const FComplexe* p_src_exp_term = local_exp_src + expansion_Redirection_array_for_j[n] + n-j+k;
+                        //printf("expansion_Redirection_array_for_j[n] + n-j+k %d\n", expansion_Redirection_array_for_j[n] + n-j+k);
+                        int l = n-j+k;
+                        // Inner_{n-j}^{l-k} : here points on the L2L transfer function/expansion term of degree n-j and order |l-k|
+                        const FComplexe* p_Inner_term = L2L_tranfer + expansion_Redirection_array_for_j[n-j] + l-k;
+
+                        //printf("1\n");
+                        for ( ; l-k>0;  --l, --p_src_exp_term, --p_Inner_term){ /* l>0 && l-k>0 */
+                                p_target_exp_term->incReal( (p_src_exp_term->getReal() * p_Inner_term->getReal()) -
+                                                            (p_src_exp_term->getImag() * p_Inner_term->getImag()));
+                                p_target_exp_term->incImag( (p_src_exp_term->getImag() * p_Inner_term->getReal()) +
+                                                            (p_src_exp_term->getReal() * p_Inner_term->getImag()));
+                                /*printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n",
+                                       p_src_exp_term->getReal(),p_src_exp_term->getImag());
+                                printf("\t p_Inner_term->real = %lf \t p_Inner_term->imag = %lf \n",
+                                       p_Inner_term->getReal(),p_Inner_term->getImag());
+                                printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n",
+                                       p_target_exp_term->getReal(),p_target_exp_term->getImag());
+                                printf("\tp_target_exp_term = %d\n",p_target_exp_term-local_exp_target);*/
+                        }
+
+                        //printf("2\n");
+                        // (-1)^l
+                        double pow_of_minus_1_for_l = ((l%2) ? -1 : 1);
+                        for (; l>0 && l>=j-n+k; --l, pow_of_minus_1_for_l = -pow_of_minus_1_for_l, --p_src_exp_term, ++p_Inner_term){ /* l>0 && l-k<=0 */
+                                p_target_exp_term->incReal( pow_of_minus_1_for_l * pow_of_minus_1_for_k *
+                                                ((p_src_exp_term->getReal() * p_Inner_term->getReal()) +
+                                                (p_src_exp_term->getImag() * p_Inner_term->getImag())));
+                                p_target_exp_term->incImag( pow_of_minus_1_for_l * pow_of_minus_1_for_k *
+                                                ((p_src_exp_term->getImag() * p_Inner_term->getReal()) -
+                                                (p_src_exp_term->getReal() * p_Inner_term->getImag())));
+                                /*printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n",
+                                       p_src_exp_term->getReal(),p_src_exp_term->getImag());
+                                printf("\t p_Inner_term->real = %lf \t p_Inner_term->imag = %lf \n",
+                                       p_Inner_term->getReal(),p_Inner_term->getImag());
+                                printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n",
+                                       p_target_exp_term->getReal(),p_target_exp_term->getImag());
+                                printf("\tp_target_exp_term = %d\n",p_target_exp_term-local_exp_target);*/
+                        }
+
+                        //printf("3\n");
+                        // l<=0 && l-k<=0
+                        for (; l>=j-n+k; --l, ++p_src_exp_term, ++p_Inner_term){
+                                p_target_exp_term->incReal( pow_of_minus_1_for_k *
+                                                ((p_src_exp_term->getReal() * p_Inner_term->getReal()) -
+                                                (p_src_exp_term->getImag() * p_Inner_term->getImag())));
+                                p_target_exp_term->decImag( pow_of_minus_1_for_k *
+                                                ((p_src_exp_term->getImag() * p_Inner_term->getReal()) +
+                                                (p_src_exp_term->getReal() * p_Inner_term->getImag())));
+                                /*printf("\t p_src_exp_term->real = %lf \t p_src_exp_term->imag = %lf \n",
+                                       p_src_exp_term->getReal(),p_src_exp_term->getImag());
+                                printf("\t p_Inner_term->real = %lf \t p_Inner_term->imag = %lf \n",
+                                       p_Inner_term->getReal(),p_Inner_term->getImag());
+                                printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n",
+                                       p_target_exp_term->getReal(),p_target_exp_term->getImag());
+                                printf("\tj=%d\tk=%d\tn=%d\tl=%d\tpow_of_minus_1_for_k=%f\n",j,k,n,l,pow_of_minus_1_for_k);
+                                printf("\tp_target_exp_term = %d\n",p_target_exp_term-local_exp_target);*/
+                        }
+                        //printf("\tj=%d\tk=%d\tn=%d\tl=%d\n",j,k,n,l);
+                        //printf("\t\t p_target_exp_term->real = %lf \t p_target_exp_term->imag = %lf \n",
+                        //       p_target_exp_term->getReal(),p_target_exp_term->getImag());
+                    }
+                }
+            }
+        }
+    }
+
+    /** bodies_L2P
+      * expansion_L2P_add_to_force_vector
+      */
+    void L2P(CellClass* const local, FList<ParticuleClass*>* const particules){
+        typename FList<ParticuleClass*>::BasicIterator iterTarget(*particules);
+        while( iterTarget.isValide() ){
+
+              F3DPosition force_vector_in_local_base;
+              Spherical spherical;
+
+              positionToSphere( iterTarget.value()->getPosition() - local->getPosition(), &spherical );
+
+              harmonicInnerThetaDerivated( spherical, current_thread_Y, current_thread_Y_theta_derivated);
+
+              // The maximum degree used here will be P.
+              FComplexe* p_Y_term = current_thread_Y+1;
+              FComplexe* p_Y_theta_derivated_term = current_thread_Y_theta_derivated+1;
+              FComplexe* p_local_exp_term = local->getLocal()+1;
+              for (int j = 1 ; j <= FMB_Info_P ; ++j ){
+                FComplexe exp_term_aux;
+
+                // k=0:
+                // F_r:
+                exp_term_aux.setReal( (p_Y_term->getReal() * p_local_exp_term->getReal()) - (p_Y_term->getImag() * p_local_exp_term->getImag()) );
+                exp_term_aux.setImag( (p_Y_term->getReal() * p_local_exp_term->getImag()) + (p_Y_term->getImag() * p_local_exp_term->getReal()) );
+
+                force_vector_in_local_base.setX( force_vector_in_local_base.getX() + j * exp_term_aux.getReal());
+                // F_phi: k=0 => nothing to do for F_phi
+                // F_theta:
+                exp_term_aux.setReal( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getReal()) - (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getImag()) );
+                exp_term_aux.setImag( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getImag()) + (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getReal()) );
+
+                force_vector_in_local_base.setY( force_vector_in_local_base.getY() + exp_term_aux.getReal());
+
+                ++p_local_exp_term;
+                ++p_Y_term;
+                ++p_Y_theta_derivated_term;
+
+
+                // k>0:
+                for (int k=1; k<=j ;++k, ++p_local_exp_term, ++p_Y_term, ++p_Y_theta_derivated_term){
+                  // F_r:
+
+                  exp_term_aux.setReal( (p_Y_term->getReal() * p_local_exp_term->getReal()) - (p_Y_term->getImag() * p_local_exp_term->getImag()) );
+                  exp_term_aux.setImag( (p_Y_term->getReal() * p_local_exp_term->getImag()) + (p_Y_term->getImag() * p_local_exp_term->getReal()) );
+
+                  force_vector_in_local_base.setX(force_vector_in_local_base.getX() + 2 * j * exp_term_aux.getReal());
+                  // F_phi:
+                  force_vector_in_local_base.setZ( force_vector_in_local_base.getZ() - 2 * k * exp_term_aux.getImag());
+                  // F_theta:
+
+                  exp_term_aux.setReal( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getReal()) - (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getImag()) );
+                  exp_term_aux.setImag( (p_Y_theta_derivated_term->getReal() * p_local_exp_term->getImag()) + (p_Y_theta_derivated_term->getImag() * p_local_exp_term->getReal()) );
+
+                  force_vector_in_local_base.setY(force_vector_in_local_base.getY() + 2 * exp_term_aux.getReal());
+                }
+              }
+
+              // We want: - gradient(POTENTIAL_SIGN potential).
+              // The -(- 1.0) computing is not the most efficient programming ...
+            //#define FMB_TMP_SIGN -(POTENTIAL_SIGN 1.0)
+              force_vector_in_local_base.setX( force_vector_in_local_base.getX() * (-1.0) / spherical.r);
+              force_vector_in_local_base.setY( force_vector_in_local_base.getY() * (-1.0) / spherical.r);
+              force_vector_in_local_base.setZ( force_vector_in_local_base.getZ() * (-1.0) / (spherical.r * spherical.sinTheta));
+            //#undef FMB_TMP_SIGN
+
+              const double th = FMath::ACos(spherical.cosTheta);
+              const double cos_theta = FMath::Cos(th);
+              const double cos_phi = FMath::Cos(spherical.phi);
+              const double sin_theta = FMath::Sin(th);
+              const double sin_phi = FMath::Sin(spherical.phi);
+
+              F3DPosition force_vector_tmp;
+
+              force_vector_tmp.setX(
+                             cos_phi * sin_theta * force_vector_in_local_base.getX() +
+                             cos_phi * cos_theta * force_vector_in_local_base.getY() +
+                             (-sin_phi) * force_vector_in_local_base.getZ());
+
+              force_vector_tmp.setY(
+                             sin_phi * sin_theta * force_vector_in_local_base.getX() +
+                             sin_phi * cos_theta * force_vector_in_local_base.getY() +
+                             cos_phi * force_vector_in_local_base.getZ());
+
+              force_vector_tmp.setZ(
+                             cos_theta * force_vector_in_local_base.getX() +
+                             (-sin_theta) * force_vector_in_local_base.getY());
+
+
+            //#ifndef _DIRECT_MATRIX_
+              // When _DIRECT_MATRIX_ is defined, this multiplication is done in 'leaf_Sum_near_and_far_fields()'
+              force_vector_tmp *= iterTarget.value()->getValue();
+            //#endif
+
+              iterTarget.value()->setForces( iterTarget.value()->getForces() + force_vector_tmp );
+
+              //printf("Morton %lld \t fx = %f \t fy = %f \t fz = %f \n",local->getMortonIndex(),iterTarget.value()->getForces().getX(),iterTarget.value()->getForces().getY(),iterTarget.value()->getForces().getZ());
+
+            iterTarget.progress();
+        }
+    }
+
+
+
+
+
+
+    /** void bodies_Compute_direct_interaction 	(
+                bodies_t *FMB_RESTRICT  	p_b_target,
+                bodies_t *FMB_RESTRICT  	p_b_src,
+                bool  	mutual
+        )
+      *
+      */
+    void P2P(FList<ParticuleClass*>* const currentBox, FList<ParticuleClass*>** directNeighbors, const int size) {
+        typename FList<ParticuleClass*>::BasicIterator iterTarget(*currentBox);
+        while( iterTarget.isValide() ){
+            for(int idxDirectNeighbors = 0 ; idxDirectNeighbors < size ; ++idxDirectNeighbors){
+                typename FList<ParticuleClass*>::BasicIterator iterSource(*currentBox);
+                while( iterSource.isValide() ){
+                  DIRECT_COMPUTATION_NO_MUTUAL_SOFT(&iterTarget.value(),
+                                                   iterSource.value());
+                  iterSource.progress();
+                }
+             }
+
+            typename FList<ParticuleClass*>::BasicIterator iterSameBox(*currentBox);
+            while( iterSameBox.isValide() ){
+                if(iterSameBox.value() != iterTarget.value()){
+                    DIRECT_COMPUTATION_NO_MUTUAL_SOFT(&iterTarget.value(),
+                                                     iterSameBox.value());
+                }
+                iterSameBox.progress();
+            }
+
+            //printf("x = %f \t y = %f \t z = %f \n",iterTarget.value()->getPosition().getX(),iterTarget.value()->getPosition().getY(),iterTarget.value()->getPosition().getZ());
+            //printf("\t fx = %f \t fy = %f \t fz = %f \n",iterTarget.value()->getForces().getX(),iterTarget.value()->getForces().getY(),iterTarget.value()->getForces().getZ());
+            //printf("\t potential = %f \n",iterTarget.value()->getPotential());
+
+            force_sum += iterTarget.value()->getForces();
+            potential_sum += iterTarget.value()->getPotential();
+
+            iterTarget.progress();
+        }
+    }
+    void DIRECT_COMPUTATION_NO_MUTUAL_SOFT(ParticuleClass** const target, const ParticuleClass* const source){
+      const double dx = (*target)->getPosition().getX() - source->getPosition().getX();
+      const double dy = (*target)->getPosition().getY() - source->getPosition().getY();
+      const double dz = (*target)->getPosition().getZ() - source->getPosition().getZ();
+
+      double inv_square_distance = 1.0/ (dx*dx + dy*dy + dz*dz + FMB_Info_eps_soft_square);
+      double inv_distance = FMath::Sqrt(inv_square_distance);
+      inv_distance *= (*target)->getValue() * source->getValue();
+      inv_square_distance *= inv_distance;
+
+      //#ifdef _FORCES_
+      (*target)->setForces(
+              (*target)->getForces().getX() + dx * inv_square_distance,
+              (*target)->getForces().getY() + dy * inv_square_distance,
+              (*target)->getForces().getZ() + dz * inv_square_distance
+      );
+      //#endif
+
+      //#ifdef _ENERGY_
+      (*target)->setPotential( inv_distance + (*target)->getPotential());
+      //#endif
+    }
+};
+
+
+template< class ParticuleClass, class CellClass>
+const double FFmbKernels<ParticuleClass,CellClass>::PiArrayInner[4] = {0, FMath::FPiDiv2, FMath::FPi, -FMath::FPiDiv2};
+
+
+template< class ParticuleClass, class CellClass>
+const double FFmbKernels<ParticuleClass,CellClass>::PiArrayOuter[4] = {0, -FMath::FPiDiv2, FMath::FPi, FMath::FPiDiv2};
+
+
+
+#endif //FFMBKERNELS_HPP
+
+// [--LICENSE--]