FOctreeArranger.hpp 4.35 KB
Newer Older
1
// ===================================================================================
2 3 4 5 6 7 8 9
// Logiciel initial: ScalFmm Version 0.5
// Co-auteurs : Olivier Coulaud, Bérenger Bramas.
// Propriétaires : INRIA.
// Copyright © 2011-2012, diffusé sous les termes et conditions d’une licence propriétaire.
// Initial software: ScalFmm Version 0.5
// Co-authors: Olivier Coulaud, Bérenger Bramas.
// Owners: INRIA.
// Copyright © 2011-2012, spread under the terms and conditions of a proprietary license.
10
// ===================================================================================
11 12 13 14
#ifndef FOCTREEARRANGER_HPP
#define FOCTREEARRANGER_HPP

#include "../Utils/FGlobal.hpp"
15
#include "../Utils/F3DPosition.hpp"
16 17 18
#include "../Containers/FVector.hpp"
#include "../Utils/FAssertable.hpp"

19 20 21 22

/** This class is an arranger, it move the particles that need
  * to be hosted in a different leaf
  */
23
template <class OctreeClass, class ContainerClass, class ParticleClass>
24
class FOctreeArranger : FAssertable {
25
    OctreeClass* const tree; //< The tree to work on
26 27

public:
28
    /** Basic constructor */
29 30 31 32
    FOctreeArranger(OctreeClass* const inTree) : tree(inTree) {
        fassert(tree, "Tree cannot be null", __LINE__ , __FILE__ );
    }

33
    /** Arrange */
34
    void rearrange(const bool isPeriodic = false){
35
        // This vector is to keep the moving particles
36
        FVector<ParticleClass> tomove;
37

38 39 40 41 42
        // For periodic
        const FReal boxWidth = tree->getBoxWidth();
        const F3DPosition min(tree->getBoxCenter(),-boxWidth/2);
        const F3DPosition max(tree->getBoxCenter(),boxWidth/2);

43 44 45 46
        { // iterate on the leafs and found particle to remove
            typename OctreeClass::Iterator octreeIterator(tree);
            octreeIterator.gotoBottomLeft();
            do{
47
                const MortonIndex currentIndex = octreeIterator.getCurrentGlobalIndex();
48 49 50

                typename ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListTargets());
                while( iter.hasNotFinished() ){
51 52 53 54 55
                    if(isPeriodic){
                        F3DPosition partPos = iter.data().getPosition();
                        while(partPos.getX() < min.getX()){
                            partPos.incX(boxWidth);
                        }
berenger-bramas's avatar
berenger-bramas committed
56
                        while(partPos.getX() >= max.getX()){
57 58 59 60 61
                            partPos.incX(-boxWidth);
                        }
                        while(partPos.getY() < min.getY()){
                            partPos.incY(boxWidth);
                        }
berenger-bramas's avatar
berenger-bramas committed
62
                        while(partPos.getY() >= max.getY()){
63 64 65 66 67
                            partPos.incY(-boxWidth);
                        }
                        while(partPos.getZ() < min.getZ()){
                            partPos.incZ(boxWidth);
                        }
berenger-bramas's avatar
berenger-bramas committed
68
                        while(partPos.getZ() >= max.getZ()){
69 70 71 72
                            partPos.incZ(-boxWidth);
                        }
                        iter.data().setPosition(partPos);
                    }
73 74 75 76 77 78 79 80 81 82 83
                    const MortonIndex particuleIndex = tree->getMortonFromPosition(iter.data().getPosition());
                    if(particuleIndex != currentIndex){
                        tomove.push(iter.data());
                        iter.remove();
                    }
                    else {
                        iter.gotoNext();
                    }
                }
            } while(octreeIterator.moveRight());
        }
84

85 86 87 88 89
        { // insert particles that moved
            for(int idxPart = 0 ; idxPart < tomove.getSize() ; ++idxPart){
                tree->insert(tomove[idxPart]);
            }
        }
90

91 92 93 94 95 96 97
        { // Remove empty leaves
            typename OctreeClass::Iterator octreeIterator(tree);
            octreeIterator.gotoBottomLeft();
            bool workOnNext = true;
            do{
                // Empty leaf
                if( octreeIterator.getCurrentListTargets()->getSize() == 0 ){
98
                    const MortonIndex currentIndex = octreeIterator.getCurrentGlobalIndex();
99 100 101 102 103 104 105 106 107 108 109 110 111 112
                    workOnNext = octreeIterator.moveRight();
                    tree->removeLeaf( currentIndex );
                }
                // Not empty, just continue
                else {
                    workOnNext = octreeIterator.moveRight();
                }
            } while( workOnNext );
        }
    }

};

#endif // FOCTREEARRANGER_HPP