Commit fccc405d authored by berenger-bramas's avatar berenger-bramas

Improve Octree and suboctree (create a delete method to remove a cell)

add a remove methode to the vector.

Create an arranger for the octree in shared memory.

git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/scalfmm/scalfmm/trunk@261 2616d619-271b-44dc-8df4-d4a8f33a7222
parent ce4b73a0
#ifndef FOCTREEARRANGER_HPP
#define FOCTREEARRANGER_HPP
#include "../Utils/FGlobal.hpp"
#include "../Containers/FVector.hpp"
#include "../Utils/FAssertable.hpp"
template <class OctreeClass, class ParticleClass>
class FOctreeArranger : FAssertable {
OctreeClass* const tree;
public:
FOctreeArranger(OctreeClass* const inTree) : tree(inTree) {
fassert(tree, "Tree cannot be null", __LINE__ , __FILE__ );
}
void rearrange(){
FVector<CellClass> tomove;
{ // iterate on the leafs and found particle to remove
typename OctreeClass::Iterator octreeIterator(tree);
octreeIterator.gotoBottomLeft();
do{
const MortonIndex currentIndex = octreeIterator.currentGlobalIndex();
typename ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListTargets());
while( iter.hasNotFinished() ){
const MortonIndex particuleIndex = tree->getMortonFromPosition(iter.data().getPosition());
if(particuleIndex != currentIndex){
tomove.push(iter.data());
iter.remove();
}
else {
iter.gotoNext();
}
}
} while(octreeIterator.moveRight());
}
{ // insert particles that moved
for(int idxPart = 0 ; idxPart < tomove.getSize() ; ++idxPart){
tree->insert(tomove[idxPart]);
}
}
{ // Remove empty leaves
typename OctreeClass::Iterator octreeIterator(tree);
octreeIterator.gotoBottomLeft();
bool workOnNext = true;
do{
// Empty leaf
if( octreeIterator.getCurrentListTargets()->getSize() == 0 ){
const MortonIndex currentIndex = octreeIterator.currentGlobalIndex();
workOnNext = octreeIterator.moveRight();
tree->removeLeaf( currentIndex );
}
// Not empty, just continue
else {
workOnNext = octreeIterator.moveRight();
}
} while( workOnNext );
}
}
};
#endif // FOCTREEARRANGER_HPP
......@@ -141,6 +141,22 @@ public:
root.insert( particleIndex, host, inParticle, this->height, this->boxWidthAtLevel);
}
/** Remove a leaf from its morton index
* @param the index of the leaf to remove
*/
void removeLeaf(const MortonIndex indexToRemove ){
root.removeLeaf( indexToRemove , this->height);
}
/**
* Get a morton index from a real position
* @param a position to compute MI
* @return the morton index
*/
MortonIndex getMortonFromPosition(const F3DPosition& position) const {
return getCoordinateFromPosition(position).getMortonIndex(leafIndex);
}
/**
* The class works on suboctree. Most of the resources needed
* are avaiblable by using FAbstractSubOctree. But when accessing
......
......@@ -114,6 +114,51 @@ protected:
if(arrayIndex > this->rightLeafIndex) this->rightLeafIndex = arrayIndex;
}
/** Remove every cells from the array index
* the leaf cell is removed, then we go upper and test,
* does the upper cell do no have any more child, if tree remove
* this cell too and go upper, etc.
* @return true if there is no more cells in this tree
*/
bool removeCellsFromLeaf( long arrayIndex ){
// last array index
int indexLevel = this->subOctreeHeight - 1;
// Manage border limits
if(arrayIndex == this->leftLeafIndex && arrayIndex == this->rightLeafIndex){
// only one cells, return true
return true;
}
else if(arrayIndex == this->leftLeafIndex){
while( !this->cells[indexLevel][++this->leftLeafIndex] );
}
else if(arrayIndex == this->rightLeafIndex){
while( !this->cells[indexLevel][--this->rightLeafIndex] );
}
// remove the last cells
delete this->cells[indexLevel][arrayIndex];
this->cells[indexLevel][arrayIndex] = 0;
// progress upper
--indexLevel;
arrayIndex >>= 3;
// to test if 8 child are empty
CellClass* emptyArray[8];
memset(emptyArray , 0, sizeof(CellClass*) * 8);
// continue while we are not in the last level and our child are empty
while(indexLevel >= 0 && memcmp(&this->cells[indexLevel+1][arrayIndex<<3], emptyArray, 8 * sizeof(CellClass*)) == 0 ){
delete this->cells[indexLevel][arrayIndex];
this->cells[indexLevel][arrayIndex] = 0;
--indexLevel;
arrayIndex >>= 3;
}
// return true if there is no more child == 0 cell at level 0
return memcmp(this->cells[0], emptyArray, 8 * sizeof(CellClass*)) == 0;
}
/** Disable copy */
private:
FAbstractSubOctree(const FAbstractSubOctree&){}
......@@ -178,6 +223,12 @@ public:
*/
virtual void insert(const MortonIndex index, const FTreeCoordinate& host, const ParticleClass& inParticle, const int inTreeHeight, const FReal* const inBoxWidthAtLevel) = 0;
/**
* Remove a leaf and every cells if needed
* @return true if the subtree does not contains any more cells
*/
virtual bool removeLeaf(const MortonIndex index, const int inTreeHeight) = 0;
///////////////////////////////////////
// This is the FOctree::Iterator Part
///////////////////////////////////////
......@@ -330,6 +381,22 @@ public:
this->leafs[arrayIndex]->push(inParticle);
}
/**
* Remove a leaf and every cells if needed
*/
bool removeLeaf(const MortonIndex index, const int inTreeHeight) {
// Get the morton index for the leaf level
const MortonIndex arrayIndex = FAbstractSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass>::getLeafIndex(index,inTreeHeight);
if( this->leafs[arrayIndex] ){
// remove container
delete this->leafs[arrayIndex];
this->leafs[arrayIndex] = 0;
return FAbstractSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass>::removeCellsFromLeaf( long(arrayIndex) );
}
return false;
}
/** To get access to leafs elements
* @param index the position of the leaf
* @return the list of particles at this index */
......@@ -461,6 +528,22 @@ public:
this->subleafs[arrayIndex]->insert( index, host, inParticle, inTreeHeight, inBoxWidthAtLevel);
}
/**
* Remove a leaf and every cells if needed
*/
bool removeLeaf(const MortonIndex index, const int inTreeHeight) {
// Get the morton index for the leaf level
const MortonIndex arrayIndex = FAbstractSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass>::getLeafIndex(index,inTreeHeight);
if( this->subleafs[arrayIndex]->removeLeaf(index, inTreeHeight) ){
// remove container
delete this->subleafs[arrayIndex];
this->subleafs[arrayIndex] = 0;
return FAbstractSubOctree<ParticleClass,CellClass,ContainerClass,LeafClass>::removeCellsFromLeaf( long(arrayIndex) );
}
return false;
}
/** To get access to leafs elements (child suboctree)
* @param index the position of the leaf/child suboctree
* @return child at this index */
......
......@@ -220,27 +220,44 @@ public:
int index; /**< the current node*/
public:
/** Empty destructor */
virtual ~BasicIterator(){}
/** Constructor need a vector */
BasicIterator(FVector<T>& inVector) : vector(&inVector), index(0){}
/** Go to next vector element */
void gotoNext(){
++this->index;
}
/** is it over
* @return true if we are over the vector
*/
bool hasNotFinished() const{
return this->index < this->vector->index;
}
/** Get current data */
T& data(){
return this->vector->array[this->index];
}
/** Get current data */
const T& data() const{
return this->vector->array[this->index];
}
/** Remove current data */
void remove(){
if( hasNotFinished() ){
for(int idxMove = this->index + 1; idxMove < this->vector->index ; ++idxMove){
vector->array[idxMove - 1] = vector->array[idxMove];
}
this->vector->index -= 1;
}
}
};
friend class BasicIterator;
......@@ -253,19 +270,25 @@ public:
int index; /**< the current node*/
public:
/** Empty destructor */
virtual ~ConstBasicIterator(){}
/** Constructor need a vector */
ConstBasicIterator(const FVector<T>& inVector) : vector(&inVector), index(0){}
/** Go to next vector element */
void gotoNext(){
++this->index;
}
/** is it over
* @return true if we are over the vector
*/
bool hasNotFinished() const{
return this->index < this->vector->index;
}
/** Get current data */
const T& data() const{
return this->vector->array[this->index];
}
......
......@@ -78,7 +78,7 @@ class TestVector : public FUTester<TestVector> {
void TestIter(){
FVector<TestObject> vector;
{
FVector<TestObject>::BasicIterator iter(vector);
FVector<TestObject>::ConstBasicIterator iter(vector);
assert(!iter.hasNotFinished());
}
{
......@@ -86,7 +86,7 @@ class TestVector : public FUTester<TestVector> {
vector.push(TestObject());
vector.push(TestObject());
FVector<TestObject>::BasicIterator iter(vector);
FVector<TestObject>::ConstBasicIterator iter(vector);
assert(iter.hasNotFinished());
int counter = 0;
......@@ -95,12 +95,39 @@ class TestVector : public FUTester<TestVector> {
assert(counter == vector.getSize());
}
}
// test remove
void TestRemove(){
FVector<TestObject> vector;
{
FVector<TestObject>::BasicIterator iter(vector);
assert(!iter.hasNotFinished());
}
{
vector.push(TestObject());
vector.push(TestObject());
vector.push(TestObject());
FVector<TestObject>::BasicIterator iter(vector);
assert(iter.hasNotFinished());
iter.gotoNext();
iter.remove();
assert(iter.hasNotFinished());
iter.gotoNext();
assert(!iter.hasNotFinished());
assert(2 == vector.getSize());
}
}
// set test
void SetTests(){
AddTest(&TestVector::TestSize,"Test Size");
AddTest(&TestVector::TestCopy,"Test Copy");
AddTest(&TestVector::TestIter,"Test Iter");
AddTest(&TestVector::TestRemove,"Test Remove");
}
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment