From 68f27f532fc0cfd1540fb154b5c710946525841d Mon Sep 17 00:00:00 2001
From: bramas <berenger.bramas@inria.fr>
Date: Thu, 3 Apr 2014 17:54:04 +0200
Subject: [PATCH] add a group algorithm (sequential and absolutly not tested)

---
 Src/GroupTree/FGroupSeqAlgorithm.hpp | 390 +++++++++++++++++++++++++++
 Src/GroupTree/FGroupTree.hpp         | 101 +++++--
 Tests/Kernels/testBlockedTree.cpp    |   8 +-
 3 files changed, 470 insertions(+), 29 deletions(-)
 create mode 100644 Src/GroupTree/FGroupSeqAlgorithm.hpp

diff --git a/Src/GroupTree/FGroupSeqAlgorithm.hpp b/Src/GroupTree/FGroupSeqAlgorithm.hpp
new file mode 100644
index 000000000..e7976d4ca
--- /dev/null
+++ b/Src/GroupTree/FGroupSeqAlgorithm.hpp
@@ -0,0 +1,390 @@
+#ifndef FGROUPSEQALGORITHM_HPP
+#define FGROUPSEQALGORITHM_HPP
+
+#include "../Utils/FGlobal.hpp"
+#include "../Core/FCoreCommon.hpp"
+#include "../Utils/FQuickSort.hpp"
+#include "../Containers/FTreeCoordinate.hpp"
+
+#include <list>
+#include <vector>
+
+template <class OctreeClass, class CellContainerClass, class CellClass, class KernelClass, class ParticleContainerClass>
+class FGroupSeqAlgorithm {
+protected:
+    struct OutOfBlockInteraction{
+        MortonIndex outIndex;
+        MortonIndex insideIndex;
+        int outPosition;
+
+        operator long long() const{
+            return static_cast<long long>(outIndex);
+        }
+    };
+
+    const int MaxThreads;         //< The number of threads
+    OctreeClass*const tree;       //< The Tree
+    KernelClass*const kernels;    //< The kernels
+
+public:
+    FGroupSeqAlgorithm(OctreeClass*const inTree, KernelClass* inKernels) : MaxThreads(1), tree(inTree), kernels(inKernels){
+        FAssertLF(tree, "tree cannot be null");
+        FAssertLF(kernels, "kernels cannot be null");
+
+        FLOG(FLog::Controller << "FGroupSeqAlgorithm (Max Thread " << MaxThreads << ")\n");
+    }
+
+    ~FGroupSeqAlgorithm(){
+    }
+
+    void execute(const unsigned operationsToProceed = FFmmNearAndFarFields){
+        if(operationsToProceed & FFmmP2M) bottomPass();
+
+        if(operationsToProceed & FFmmM2M) upwardPass();
+
+        if(operationsToProceed & FFmmM2L) transferPass();
+
+        if(operationsToProceed & FFmmL2L) downardPass();
+
+        if( (operationsToProceed & FFmmP2P) || (operationsToProceed & FFmmL2P) ) directPass();
+    }
+
+protected:
+    void bottomPass(){
+        typename std::list<ParticleContainerClass>::iterator iterParticles = tree->leavesBegin();
+        const typename std::list<ParticleContainerClass>::iterator endParticles = tree->leavesEnd();
+
+        typename std::list<CellContainerClass>::iterator iterCells = tree->cellsBegin(tree->getHeight()-1);
+        const typename std::list<CellContainerClass>::iterator endCells = tree->cellsEnd(tree->getHeight()-1);
+
+        while(iterParticles != endParticles && iterCells != endCells){
+            { // Can be a task(in:iterParticles, out:iterCells)
+                const MortonIndex blockStartIdx = (*iterCells)->getStartingIndex();
+                const MortonIndex blockEndIdx = (*iterCells)->getEndingIndex();
+
+                for(MortonIndex mindex = blockStartIdx ; mindex < blockEndIdx ; ++mindex){
+                    CellClass* cell = (*iterCells)->getCell(mindex);
+                    if(cell){
+                        ParticleContainerClass particles = (*iterParticles)->getLeaf(mindex);
+                        FAssertLF(particles.isAttachedToSomething());
+                        kernels->P2M(cell, &particles);
+                    }
+                }
+            }
+
+            ++iterParticles;
+            ++iterCells;
+        }
+
+        FAssertLF(iterParticles == endParticles && iterCells == endCells);
+    }
+
+    void upwardPass(){
+        for(int idxLevel = tree->getHeight()-2 ; idxLevel >= 2 ; --idxLevel){
+            typename std::list<CellContainerClass>::iterator iterCells = tree->cellsBegin(idxLevel);
+            const typename std::list<CellContainerClass>::iterator endCells = tree->cellsEnd(idxLevel);
+
+            typename std::list<CellContainerClass>::iterator iterChildCells = tree->cellsBegin(idxLevel+1);
+            const typename std::list<CellContainerClass>::iterator endChildCells = tree->cellsEnd(idxLevel+1);
+
+            while(iterCells != endCells && iterChildCells != endChildCells){
+                { // Can be a task(in:iterParticles, out:iterChildCells ...)
+                    const MortonIndex blockStartIdx = (*iterCells)->getStartingIndex();
+                    const MortonIndex blockEndIdx = (*iterCells)->getEndingIndex();
+
+                    for(MortonIndex mindex = blockStartIdx ; mindex < blockEndIdx && iterChildCells != endChildCells; ++mindex){
+                        CellClass* cell = (*iterCells)->getCell(mindex);
+                        if(cell){
+                            CellClass* child[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
+
+                            for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){
+                                while(iterChildCells != endChildCells && (*iterChildCells)->getEndingIndex() < ((mindex<<3)+idxChild) ){
+                                    ++iterChildCells;
+                                }
+                                if( iterChildCells == endChildCells ){
+                                    break;
+                                }
+                                child[idxChild] = (*iterChildCells)->getCell((mindex<<3)+idxChild);
+                            }
+
+                            kernels->M2M(cell, child, idxLevel);
+                        }
+                    }
+                }
+
+                ++iterCells;
+            }
+
+            FAssertLF(iterCells == endCells && (iterChildCells == endChildCells || (++iterChildCells) == endChildCells));
+        }
+    }
+
+    void transferPass(){
+        for(int idxLevel = tree->getHeight()-1 ; idxLevel >= 2 ; --idxLevel){
+            typename std::list<CellContainerClass>::iterator iterCells = tree->cellsBegin(idxLevel);
+            const typename std::list<CellContainerClass>::iterator endCells = tree->cellsEnd(idxLevel);
+
+            while(iterCells != endCells){
+                std::vector<OutOfBlockInteraction> outsideInteractions;
+
+                { // Can be a task(inout:iterCells, out:outsideInteractions)
+                    const MortonIndex blockStartIdx = (*iterCells)->getStartingIndex();
+                    const MortonIndex blockEndIdx = (*iterCells)->getEndingIndex();
+
+                    for(MortonIndex mindex = blockStartIdx ; mindex < blockEndIdx ; ++mindex){
+                        CellClass* cell = (*iterCells)->getCell(mindex);
+                        if(cell){
+                            MortonIndex interactionsIndexes[189];
+                            int interactionsPosition[189];
+                            FTreeCoordinate coord(mindex, idxLevel);
+                            int counter = coord.getInteractionNeighbors(idxLevel,interactionsIndexes,interactionsPosition);
+
+                            CellClass* interactions[343];
+                            memset(interactions, 0, 343*sizeof(CellClass*));
+                            int counterExistingCell = 0;
+
+                            for(int idxInter = 0 ; idxInter < counter ; ++idxInter){
+                                if( blockStartIdx <= interactionsIndexes[idxInter] && interactionsIndexes[idxInter] < blockEndIdx ){
+                                    CellClass* interCell = (*iterCells)->getCell(interactionsIndexes[idxInter]);
+                                    if(interCell){
+                                        interactions[interactionsPosition[idxInter]] = interCell;
+                                        counterExistingCell += 1;
+                                    }
+                                }
+                                else if(interactionsPosition[idxInter] < 343/2){
+                                    OutOfBlockInteraction property;
+                                    property.insideIndex = mindex;
+                                    property.outIndex    = interactionsIndexes[idxInter];
+                                    property.outPosition = interactionsPosition[idxInter];
+                                    outsideInteractions.push_back(property);
+                                }
+                            }
+
+                            kernels->M2L( cell , interactions, counterExistingCell, idxLevel);
+                        }
+                    }
+                }
+
+
+                // Manage outofblock interaction
+                FQuickSort<OutOfBlockInteraction, long long, int>::QsSequential(outsideInteractions.data(),outsideInteractions.size());
+
+                typename std::list<CellContainerClass>::iterator iterLeftCells = tree->cellsBegin(idxLevel);
+                int currentOutInteraction = 0;
+                while(iterLeftCells != iterCells && currentOutInteraction < outsideInteractions.size()){
+                    const MortonIndex blockStartIdx = (*iterLeftCells)->getStartingIndex();
+                    const MortonIndex blockEndIdx = (*iterLeftCells)->getEndingIndex();
+
+                    while(outsideInteractions[currentOutInteraction].outIndex < blockStartIdx){
+                        currentOutInteraction += 1;
+                    }
+
+                    int lastOutInteraction = currentOutInteraction + 1;
+                    while(lastOutInteraction < outsideInteractions.size() && outsideInteractions[lastOutInteraction].outIndex < blockEndIdx){
+                        lastOutInteraction += 1;
+                    }
+
+                    { // Can be a task(in:currentOutInteraction, in:outsideInteractions, in:lastOutInteraction, inout:iterLeftCells, inout:iterCells)
+                        for(int outInterIdx = currentOutInteraction ; outInterIdx < lastOutInteraction ; ++outInterIdx){
+                            CellClass* interCell = (*iterLeftCells)->getCell(outsideInteractions[outInterIdx].outIndex);
+                            if(interCell){
+                                CellClass* cell = (*iterCells)->getCell(outsideInteractions[outInterIdx].insideIndex);
+                                FAssertLF(cell);
+                                CellClass* interactions[343];
+                                memset(interactions, 0, 343*sizeof(CellClass*));
+                                interactions[outsideInteractions[outInterIdx].outPosition] = interCell;
+                                const int counter = 1;
+                                kernels->M2L( cell , interactions, counter, idxLevel);
+
+                                interactions[outsideInteractions[outInterIdx].outPosition] = NULL;
+                                interactions[getOppositeInterIndex(outsideInteractions[outInterIdx].outPosition)] = cell;
+                                kernels->M2L( interCell , interactions, counter, idxLevel);
+                            }
+                        }
+                    }
+
+                    currentOutInteraction = lastOutInteraction;
+                    ++iterLeftCells;
+                }
+
+                ++iterCells;
+            }
+
+        }
+    }
+
+    void downardPass(){
+        for(int idxLevel = 2 ; idxLevel <= tree->getHeight()-2 ; ++idxLevel){
+            typename std::list<CellContainerClass>::iterator iterCells = tree->cellsBegin(idxLevel);
+            const typename std::list<CellContainerClass>::iterator endCells = tree->cellsEnd(idxLevel);
+
+            typename std::list<CellContainerClass>::iterator iterChildCells = tree->cellsBegin(idxLevel+1);
+            const typename std::list<CellContainerClass>::iterator endChildCells = tree->cellsEnd(idxLevel+1);
+
+            while(iterCells != endCells && iterChildCells != endChildCells){
+                { // Can be a task(in:iterParticles, inout:iterChildCells ...)
+                    const MortonIndex blockStartIdx = (*iterCells)->getStartingIndex();
+                    const MortonIndex blockEndIdx = (*iterCells)->getEndingIndex();
+
+                    for(MortonIndex mindex = blockStartIdx ; mindex < blockEndIdx && iterChildCells != endChildCells; ++mindex){
+                        CellClass* cell = (*iterCells)->getCell(mindex);
+                        if(cell){
+                            CellClass* child[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
+
+                            for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){
+                                while(iterChildCells != endChildCells && (*iterChildCells)->getEndingIndex() < ((mindex<<3)+idxChild) ){
+                                    ++iterChildCells;
+                                }
+                                if( iterChildCells == endChildCells ){
+                                    break;
+                                }
+                                child[idxChild] = (*iterChildCells)->getCell((mindex<<3)+idxChild);
+                            }
+
+                            kernels->L2L(cell, child, idxLevel);
+                        }
+                    }
+                }
+
+                ++iterCells;
+            }
+
+            FAssertLF(iterCells == endCells && (iterChildCells == endChildCells || (++iterChildCells) == endChildCells));
+        }
+    }
+
+    void directPass(){
+        {
+            typename std::list<ParticleContainerClass>::iterator iterParticles = tree->leavesBegin();
+            const typename std::list<ParticleContainerClass>::iterator endParticles = tree->leavesEnd();
+
+            typename std::list<CellContainerClass>::iterator iterCells = tree->cellsBegin(tree->getHeight()-1);
+            const typename std::list<CellContainerClass>::iterator endCells = tree->cellsEnd(tree->getHeight()-1);
+
+            while(iterParticles != endParticles && iterCells != endCells){
+                { // Can be a task(in:iterCells, inout:iterParticles)
+                    const MortonIndex blockStartIdx = (*iterCells)->getStartingIndex();
+                    const MortonIndex blockEndIdx = (*iterCells)->getStartingIndex();
+
+                    for(MortonIndex mindex = blockStartIdx ; mindex < blockEndIdx ; ++mindex){
+                        CellClass* cell = (*iterCells)->getCell(mindex);
+                        if(cell){
+                            ParticleContainerClass particles = (*iterParticles)->getLeaf(mindex);
+                            FAssertLF(particles.isAttachedToSomething());
+                            kernels->P2M(cell, &particles);
+                        }
+                    }
+                }
+
+                ++iterParticles;
+                ++iterCells;
+            }
+
+            FAssertLF(iterParticles == endParticles && iterCells == endCells);
+        }
+        {
+            typename std::list<ParticleContainerClass>::iterator iterParticles = tree->leavesBegin();
+            const typename std::list<ParticleContainerClass>::iterator endParticles = tree->leavesEnd();
+
+            while(iterParticles != endParticles){
+                typename std::vector<OutOfBlockInteraction> outsideInteractions;
+
+                { // Can be a task(inout:iterCells, out:outsideInteractions)
+                    const MortonIndex blockStartIdx = (*iterParticles)->getStartingIndex();
+                    const MortonIndex blockEndIdx = (*iterParticles)->getEndingIndex();
+
+                    for(MortonIndex mindex = blockStartIdx ; mindex < blockEndIdx ; ++mindex){
+                        ParticleContainerClass particles = (*iterParticles)->getLeaf(mindex);
+                        if(particles.isAttachedToSomething()){
+                            MortonIndex interactionsIndexes[26];
+                            int interactionsPosition[26];
+                            FTreeCoordinate coord(mindex, tree->getHeight()-1);
+                            int counter = coord.getNeighborsIndexes(tree->getHeight(),interactionsIndexes,interactionsPosition);
+
+                            ParticleContainerClass interactionsObjects[27];
+                            ParticleContainerClass* interactions[27];
+                            memset(interactions, 0, 27*sizeof(CellClass*));
+                            int counterExistingCell = 0;
+
+                            for(int idxInter = 0 ; idxInter < counter ; ++idxInter){
+                                if( blockStartIdx <= interactionsIndexes[idxInter] && interactionsIndexes[idxInter] < blockEndIdx ){
+                                    interactionsObjects[counterExistingCell] = (*iterParticles)->getLeaf(interactionsIndexes[idxInter]);
+                                    if(interactionsObjects[counterExistingCell].isAttachedToSomething()){
+                                        interactions[interactionsPosition[idxInter]] = &interactionsObjects[counterExistingCell];
+                                        counterExistingCell += 1;
+                                    }
+                                }
+                                else if(interactionsPosition[idxInter] < 27/2){
+                                    OutOfBlockInteraction property;
+                                    property.insideIndex = mindex;
+                                    property.outIndex    = interactionsIndexes[idxInter];
+                                    property.outPosition = interactionsPosition[idxInter];
+                                    outsideInteractions.push_back(property);
+                                }
+                            }
+
+                            kernels->P2P( coord, &particles, &particles , interactions, counterExistingCell);
+                        }
+                    }
+                }
+
+
+                // Manage outofblock interaction
+                FQuickSort<OutOfBlockInteraction, long long, int>::QsSequential(outsideInteractions.data(),outsideInteractions.size());
+
+                typename std::list<ParticleContainerClass>::iterator iterLeftParticles = tree->leavesBegin();
+                int currentOutInteraction = 0;
+                while(iterLeftParticles != iterParticles && currentOutInteraction < outsideInteractions.size()){
+                    const MortonIndex blockStartIdx = (*iterLeftParticles)->getStartingIndex();
+                    const MortonIndex blockEndIdx = (*iterLeftParticles)->getEndingIndex();
+
+                    while(outsideInteractions[currentOutInteraction].outIndex < blockStartIdx){
+                        currentOutInteraction += 1;
+                    }
+
+                    int lastOutInteraction = currentOutInteraction + 1;
+                    while(lastOutInteraction < outsideInteractions.size() && outsideInteractions[lastOutInteraction].outIndex < blockEndIdx){
+                        lastOutInteraction += 1;
+                    }
+
+                    { // Can be a task(in:currentOutInteraction, in:outsideInteractions, in:lastOutInteraction, inout:iterLeftParticles, inout:iterParticles)
+                        for(int outInterIdx = currentOutInteraction ; outInterIdx < lastOutInteraction ; ++outInterIdx){
+                            ParticleContainerClass interParticles = (*iterLeftParticles)->getLeaf(outsideInteractions[outInterIdx].outIndex);
+                            if(interParticles.isAttachedToSomething()){
+                                ParticleContainerClass particles = (*iterParticles)->getLeaf(outsideInteractions[outInterIdx].insideIndex);
+                                FAssertLF(particles.isAttachedToSomething());
+                                CellClass* interactions[27];
+                                memset(interactions, 0, 27*sizeof(CellClass*));
+                                interactions[outsideInteractions[outInterIdx].outPosition] = &interParticles;
+                                const int counter = 1;
+                                kernels->P2PRemote( FTreeCoordinate(outsideInteractions[outInterIdx].insideIndex, tree->getHeight()-1), &particles, &particles , interactions, counter);
+
+                                interactions[outsideInteractions[outInterIdx].outPosition] = NULL;
+                                interactions[getOppositeNeighIndex(outsideInteractions[outInterIdx].outPosition)] = &particles;
+                                kernels->P2PRemote( FTreeCoordinate(outsideInteractions[outInterIdx].outIndex, tree->getHeight()-1), &interParticles, &interParticles , interactions, counter);
+                            }
+                        }
+                    }
+
+                    currentOutInteraction = lastOutInteraction;
+                    ++iterLeftParticles;
+                }
+
+                ++iterParticles;
+            }
+        }
+    }
+
+    int getOppositeNeighIndex(const int index) const {
+        // ((idxX+1)*3 + (idxY+1)) * 3 + (idxZ+1)
+        return 27-index;
+    }
+
+    int getOppositeInterIndex(const int index) const {
+        // ((( (xdiff+3) * 7) + (ydiff+3))) * 7 + zdiff + 3
+        return 343-index;
+    }
+};
+
+
+#endif // FGROUPSEQALGORITHM_HPP
diff --git a/Src/GroupTree/FGroupTree.hpp b/Src/GroupTree/FGroupTree.hpp
index 580c448be..45a5e6028 100644
--- a/Src/GroupTree/FGroupTree.hpp
+++ b/Src/GroupTree/FGroupTree.hpp
@@ -15,18 +15,20 @@
 
 template <class CellClass, unsigned NbAttributesPerParticle, class AttributeClass = FReal>
 class FGroupTree {
+public:
     typedef FGroupAttachedLeaf<NbAttributesPerParticle,AttributeClass> BasicAttachedClass;
+    typedef FGroupOfCells<CellClass> CellGroupClass;
 
+protected:
     //< This value is for not used cells
     static const int CellIsEmptyFlag = -1;
 
-protected:
     //< height of the tree (1 => only the root)
     const int treeHeight;
     //< max number of cells in a block
     const int nbElementsPerBlock;
     //< all the blocks of the tree
-    std::list<FGroupOfCells<CellClass>*>* cellBlocksPerLevel;
+    std::list<CellGroupClass*>* cellBlocksPerLevel;
     //< all the blocks of leaves
     std::list<FGroupOfParticles<NbAttributesPerParticle,AttributeClass>*> particleBlocks;
 
@@ -71,7 +73,7 @@ public:
         : treeHeight(inTreeHeight), nbElementsPerBlock(inNbElementsPerBlock), cellBlocksPerLevel(0),
           boxCenter(inOctreeSrc->getBoxCenter()), boxCorner(inOctreeSrc->getBoxCenter(),-(inOctreeSrc->getBoxWidth()/2)),
           boxWidth(inOctreeSrc->getBoxWidth()), boxWidthAtLeafLevel(inOctreeSrc->getBoxWidth()/FReal(1<<inTreeHeight)){
-        cellBlocksPerLevel = new std::list<FGroupOfCells<CellClass>*>[treeHeight];
+        cellBlocksPerLevel = new std::list<CellGroupClass*>[treeHeight];
 
         // Iterate on the tree and build
         typename OctreeClass::Iterator octreeIterator(inOctreeSrc);
@@ -92,7 +94,7 @@ public:
                 }
 
                 // Create a block with the apropriate parameters
-                FGroupOfCells<CellClass>*const newBlock = new FGroupOfCells<CellClass>(blockIteratorInOctree.getCurrentGlobalIndex(),
+                CellGroupClass*const newBlock = new CellGroupClass(blockIteratorInOctree.getCurrentGlobalIndex(),
                                                                  octreeIterator.getCurrentGlobalIndex()+1,
                                                                  sizeOfBlock);
                 FGroupOfParticles<NbAttributesPerParticle, AttributeClass>*const newParticleBlock = new FGroupOfParticles<NbAttributesPerParticle, AttributeClass>(blockIteratorInOctree.getCurrentGlobalIndex(),
@@ -148,7 +150,7 @@ public:
                 }
 
                 // Create a block with the apropriate parameters
-                FGroupOfCells<CellClass>*const newBlock = new FGroupOfCells<CellClass>(blockIteratorInOctree.getCurrentGlobalIndex(),
+                CellGroupClass*const newBlock = new CellGroupClass(blockIteratorInOctree.getCurrentGlobalIndex(),
                                                                  octreeIterator.getCurrentGlobalIndex()+1,
                                                                  sizeOfBlock);
                 // Initialize each cell of the block
@@ -191,7 +193,7 @@ public:
             boxCenter(inBoxCenter), boxCorner(inBoxCenter,-(inBoxWidth/2)), boxWidth(inBoxWidth),
             boxWidthAtLeafLevel(inBoxWidth/FReal(1<<inTreeHeight)){
 
-        cellBlocksPerLevel = new std::list<FGroupOfCells<CellClass>*>[treeHeight];
+        cellBlocksPerLevel = new std::list<CellGroupClass*>[treeHeight];
 
         MortonIndex* currentBlockIndexes = new MortonIndex[nbElementsPerBlock];
         // First we work at leaf level
@@ -248,7 +250,7 @@ public:
                 }
 
                 // Create a group
-                FGroupOfCells<CellClass>*const newBlock = new FGroupOfCells<CellClass>(currentBlockIndexes[0],
+                CellGroupClass*const newBlock = new CellGroupClass(currentBlockIndexes[0],
                                                                  currentBlockIndexes[sizeOfBlock-1]+1,
                                                                  sizeOfBlock);
                 FGroupOfParticles<NbAttributesPerParticle, AttributeClass>*const newParticleBlock = new FGroupOfParticles<NbAttributesPerParticle, AttributeClass>(currentBlockIndexes[0],
@@ -292,8 +294,8 @@ public:
 
         // For each level from heigth - 2 to 1
         for(int idxLevel = treeHeight-2; idxLevel > 0 ; --idxLevel){
-            typename std::list<FGroupOfCells<CellClass>*>::const_iterator iterChildCells = cellBlocksPerLevel[idxLevel+1].begin();
-            const typename std::list<FGroupOfCells<CellClass>*>::const_iterator iterChildEndCells = cellBlocksPerLevel[idxLevel+1].end();
+            typename std::list<CellGroupClass*>::const_iterator iterChildCells = cellBlocksPerLevel[idxLevel+1].begin();
+            const typename std::list<CellGroupClass*>::const_iterator iterChildEndCells = cellBlocksPerLevel[idxLevel+1].end();
 
             MortonIndex currentCellIndex = (*iterChildCells)->getStartingIndex();
             int sizeOfBlock = 0;
@@ -322,7 +324,7 @@ public:
                 // If group is full
                 if(sizeOfBlock == nbElementsPerBlock || (sizeOfBlock && iterChildCells == iterChildEndCells)){
                     // Create a group
-                    FGroupOfCells<CellClass>*const newBlock = new FGroupOfCells<CellClass>(currentBlockIndexes[0],
+                    CellGroupClass*const newBlock = new CellGroupClass(currentBlockIndexes[0],
                                                                      currentBlockIndexes[sizeOfBlock-1]+1,
                                                                      sizeOfBlock);
                     // Init cells
@@ -355,7 +357,7 @@ public:
    * create the block and the cells, using the constructor of
    * FGroupOfCells !!
    */
-    /*FGroupOfCells<CellClass> * createBlockFromArray(MortonIndex head[]){
+    /*CellGroupClass * createBlockFromArray(MortonIndex head[]){
         //Store the start and end
         MortonIndex start = head[0];
         MortonIndex end = start;
@@ -371,7 +373,7 @@ public:
             // }
         }
         //allocation of memory
-        FGroupOfCells<CellClass> * newBlock = new FGroupOfCells<CellClass>(start,end+1,count);
+        CellGroupClass * newBlock = new CellGroupClass(start,end+1,count);
         //allocation of cells
         for(int idx=0 ; idx<count ; idx++){
             newBlock->newCell(head[idx], idx);
@@ -389,7 +391,7 @@ public:
     FGroupTree(const int inTreeHeight, const int inNbElementsPerBlock, OctreeClass*const inOctreeSrc, int FLAG):
         treeHeight(inTreeHeight),nbElementsPerBlock(inNbElementsPerBlock),cellBlocksPerLevel(0)
     {
-        cellBlocksPerLevel = new std::list<FGroupOfCells<CellClass>*>[treeHeight];
+        cellBlocksPerLevel = new std::list<CellGroupClass*>[treeHeight];
         int *nbCellPerLevel = new int[treeHeight];
         inOctreeSrc->getNbCellsPerLevel(nbCellPerLevel);
         int nbLeaf = nbCellPerLevel[treeHeight-1];
@@ -423,7 +425,7 @@ public:
             idxLeafs += inNbElementsPerBlock;
 
             //creation of the block and addition to the list
-            FGroupOfCells<CellClass> * tempBlock = createBlockFromArray(head);
+            CellGroupClass * tempBlock = createBlockFromArray(head);
             cellBlocksPerLevel[treeHeight-1].push_back(tempBlock);
         }
         delete[] leafsIdx;
@@ -438,7 +440,7 @@ public:
             MortonIndex previous = -1;
 
             //Iterator over the list at a deeper level (READ)
-            typename std::list<FGroupOfCells<CellClass>*>::const_iterator curBlockRead;
+            typename std::list<CellGroupClass*>::const_iterator curBlockRead;
             for(curBlockRead = cellBlocksPerLevel[idxLevel+1].begin() ; curBlockRead != cellBlocksPerLevel[idxLevel+1].end() ; ++curBlockRead){
                 //Loop over cells in READ list
                 for(MortonIndex idxCell = (*curBlockRead)->getStartingIndex() ; idxCell < (*curBlockRead)->getEndingIndex() ; ++idxCell){
@@ -461,7 +463,7 @@ public:
                             else{
                                 //Creation of the block from head, then reset head, and
                                 //storage of new idx in new head
-                                FGroupOfCells<CellClass> * tempBlock = createBlockFromArray(head);
+                                CellGroupClass * tempBlock = createBlockFromArray(head);
                                 cellBlocksPerLevel[idxLevel].push_back(tempBlock);
 
                                 //Need a new block
@@ -475,7 +477,7 @@ public:
                 }
             }
             //Before changing Level, need to close current Block
-            FGroupOfCells<CellClass> * tempBlock = createBlockFromArray(head);
+            CellGroupClass * tempBlock = createBlockFromArray(head);
             cellBlocksPerLevel[idxLevel].push_back(tempBlock);
         }
         printf("toto \n");
@@ -490,8 +492,8 @@ public:
     /** This function dealloc the tree by deleting each block */
     ~FGroupTree(){
         for(int idxLevel = 0 ; idxLevel < treeHeight ; ++idxLevel){
-            std::list<FGroupOfCells<CellClass>*>& levelBlocks = cellBlocksPerLevel[idxLevel];
-            for (FGroupOfCells<CellClass>* block: levelBlocks){
+            std::list<CellGroupClass*>& levelBlocks = cellBlocksPerLevel[idxLevel];
+            for (CellGroupClass* block: levelBlocks){
                 delete block;
             }
         }
@@ -524,8 +526,8 @@ public:
    */
     void forEachCell(std::function<void(CellClass*)> function){
         for(int idxLevel = 0 ; idxLevel < treeHeight ; ++idxLevel){
-            std::list<FGroupOfCells<CellClass>*>& levelBlocks = cellBlocksPerLevel[idxLevel];
-            for (FGroupOfCells<CellClass>* block: levelBlocks){
+            std::list<CellGroupClass*>& levelBlocks = cellBlocksPerLevel[idxLevel];
+            for (CellGroupClass* block: levelBlocks){
                 block->forEachCell(function);
             }
         }
@@ -537,8 +539,8 @@ public:
    */
     void forEachCellWithLevel(std::function<void(CellClass*,const int)> function){
         for(int idxLevel = 0 ; idxLevel < treeHeight ; ++idxLevel){
-            std::list<FGroupOfCells<CellClass>*>& levelBlocks = cellBlocksPerLevel[idxLevel];
-            for (FGroupOfCells<CellClass>* block: levelBlocks){
+            std::list<CellGroupClass*>& levelBlocks = cellBlocksPerLevel[idxLevel];
+            for (CellGroupClass* block: levelBlocks){
                 block->forEachCell(function, idxLevel);
             }
         }
@@ -550,8 +552,8 @@ public:
    */
     template<class ParticlesAttachedClass>
     void forEachCellLeaf(std::function<void(CellClass*,ParticlesAttachedClass*)> function){
-        typename std::list<FGroupOfCells<CellClass>*>::iterator iterCells = cellBlocksPerLevel[treeHeight-1].begin();
-        const typename std::list<FGroupOfCells<CellClass>*>::iterator iterEndCells = cellBlocksPerLevel[treeHeight-1].end();
+        typename std::list<CellGroupClass*>::iterator iterCells = cellBlocksPerLevel[treeHeight-1].begin();
+        const typename std::list<CellGroupClass*>::iterator iterEndCells = cellBlocksPerLevel[treeHeight-1].end();
 
         typename std::list<FGroupOfParticles<NbAttributesPerParticle,AttributeClass>*>::iterator iterLeaves = particleBlocks.begin();
         const typename std::list<FGroupOfParticles<NbAttributesPerParticle,AttributeClass>*>::iterator iterEndLeaves = particleBlocks.end();
@@ -581,10 +583,10 @@ public:
         std::cout << "\t Group Size = " << nbElementsPerBlock << "\n";
         std::cout << "\t Tree height = " << treeHeight << "\n";
         for(int idxLevel = 1 ; idxLevel < treeHeight ; ++idxLevel){
-            std::list<FGroupOfCells<CellClass>*>& levelBlocks = cellBlocksPerLevel[idxLevel];
+            std::list<CellGroupClass*>& levelBlocks = cellBlocksPerLevel[idxLevel];
             std::cout << "Level " << idxLevel << ", there are " << levelBlocks.size() << " groups.\n";
             int idxGroup = 0;
-            for (const FGroupOfCells<CellClass>* block: levelBlocks){
+            for (const CellGroupClass* block: levelBlocks){
                 std::cout << "\t Group " << (idxGroup++);
                 std::cout << "\t Size = " << block->getNumberOfCellsInBlock();
                 std::cout << "\t Starting Index = " << block->getStartingIndex();
@@ -607,6 +609,51 @@ public:
         }
         std::cout << "There are " << totalNbParticles << " particles.\n";
     }
+
+    /////////////////////////////////////////////////////////
+    // Algorithm function
+    /////////////////////////////////////////////////////////
+
+    int getHeight() const {
+        return treeHeight;
+    }
+
+    typename std::list<CellGroupClass*>::iterator cellsBegin(const int atHeight){
+        FAssertLF(atHeight < treeHeight);
+        return cellBlocksPerLevel[atHeight].begin();
+    }
+
+    typename std::list<CellGroupClass*>::const_iterator cellsBegin(const int atHeight) const {
+        FAssertLF(atHeight < treeHeight);
+        return cellBlocksPerLevel[atHeight].begin();
+    }
+
+    typename std::list<CellGroupClass*>::iterator cellsEnd(const int atHeight){
+        FAssertLF(atHeight < treeHeight);
+        return cellBlocksPerLevel[atHeight].end();
+    }
+
+    typename std::list<CellGroupClass*>::const_iterator cellsEnd(const int atHeight) const {
+        FAssertLF(atHeight < treeHeight);
+        return cellBlocksPerLevel[atHeight].end();
+    }
+
+
+    typename std::list<FGroupOfParticles<NbAttributesPerParticle,AttributeClass>*>::iterator leavesBegin(){
+        return particleBlocks.begin();
+    }
+
+    typename std::list<FGroupOfParticles<NbAttributesPerParticle,AttributeClass>*>::const_iterator leavesBegin() const {
+        return particleBlocks.begin();
+    }
+
+    typename std::list<FGroupOfParticles<NbAttributesPerParticle,AttributeClass>*>::iterator leavesEnd(){
+        return particleBlocks.end();
+    }
+
+    typename std::list<FGroupOfParticles<NbAttributesPerParticle,AttributeClass>*>::const_iterator leavesEnd() const {
+        return particleBlocks.end();
+    }
 };
 
 #endif // FGROUPTREE_HPP
diff --git a/Tests/Kernels/testBlockedTree.cpp b/Tests/Kernels/testBlockedTree.cpp
index 5db219340..d8327f021 100644
--- a/Tests/Kernels/testBlockedTree.cpp
+++ b/Tests/Kernels/testBlockedTree.cpp
@@ -23,7 +23,7 @@
 
 #include "../../Src/Files/FFmaBinLoader.hpp"
 
-
+#include "../../Src/GroupTree/FGroupSeqAlgorithm.hpp"
 
 int main(int argc, char* argv[]){
     static const int P = 9;
@@ -32,7 +32,6 @@ int main(int argc, char* argv[]){
 
     typedef FSimpleLeaf< ContainerClass >                     LeafClass;
     typedef FOctree< CellClass, ContainerClass , LeafClass >  OctreeClass;
-    //typedef FRotationKernel< CellClass, ContainerClass , P>   KernelClass;
     typedef FGroupTree< CellClass, 4, FReal>  GroupOctreeClass;
 
     FTic counter;
@@ -70,5 +69,10 @@ int main(int argc, char* argv[]){
     groupedTree2.printInfoBlocks();
     groupedTree3.printInfoBlocks();
 
+
+
+    typedef FRotationKernel< CellClass, ContainerClass , P>   KernelClass;
+    FGroupSeqAlgorithm<GroupOctreeClass, typename GroupOctreeClass::CellGroupClass, CellClass, KernelClass, typename GroupOctreeClass::BasicAttachedClass> algo(NULL,NULL);
+
     return 0;
 }
-- 
GitLab