utestFmmAlgorithmProc.cpp 10.9 KB
Newer Older
1
// See LICENCE file at project root
2 3 4 5 6 7 8

// ==== CMAKE =====
// @FUSE_MPI
// ================

#include "FUTester.hpp"

BRAMAS Berenger's avatar
BRAMAS Berenger committed
9 10
#include "Utils/FMpi.hpp"
#include "Utils/FTic.hpp"
11

BRAMAS Berenger's avatar
BRAMAS Berenger committed
12 13 14 15
#include "Containers/FOctree.hpp"
#include "Containers/FVector.hpp"
#include "Utils/FParameters.hpp"
#include "Utils/FGlobal.hpp"
16

BRAMAS Berenger's avatar
BRAMAS Berenger committed
17
#include "Components/FSimpleLeaf.hpp"
18

BRAMAS Berenger's avatar
BRAMAS Berenger committed
19
#include "Utils/FPoint.hpp"
20

BRAMAS Berenger's avatar
BRAMAS Berenger committed
21 22 23
#include "Components/FTestCell.hpp"
#include "Components/FTestKernels.hpp"
#include "Components/FTestParticleContainer.hpp"
24

BRAMAS Berenger's avatar
BRAMAS Berenger committed
25 26
#include "Core/FFmmAlgorithmThreadProc.hpp"
#include "Core/FFmmAlgorithmThread.hpp"
27

BRAMAS Berenger's avatar
BRAMAS Berenger committed
28 29
#include "Files/FMpiFmaGenericLoader.hpp"
#include "Files/FMpiTreeBuilder.hpp"
30

BRAMAS Berenger's avatar
BRAMAS Berenger committed
31
#include "Components/FBasicKernels.hpp"
32

33
#include "Utils/FLeafBalance.hpp"
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189

#include <iostream>
#include <cstdio>
#include <cstdlib>


/** this class test the bool array container */
class TestFmmAlgoProc : public FUTesterMpi<TestFmmAlgoProc> {

    // Check if tree is built correctly
    template<class OctreeClass>
    void ValidateTree(OctreeClass& realTree, OctreeClass& treeValide){

        typename OctreeClass::Iterator octreeIteratorValide(&treeValide);
        octreeIteratorValide.gotoBottomLeft();

        typename OctreeClass::Iterator octreeIterator(&realTree);
        octreeIterator.gotoBottomLeft();

        while(octreeIteratorValide.getCurrentGlobalIndex() != octreeIterator.getCurrentGlobalIndex()){
            if(octreeIteratorValide.moveRight() == false){
                uassert(false);
                return;
            }
        }

        while(true){
            if(octreeIteratorValide.getCurrentGlobalIndex() != octreeIterator.getCurrentGlobalIndex()){
                uassert(false);
                return;
            }

            if(octreeIteratorValide.getCurrentListSrc()->getNbParticles() != octreeIterator.getCurrentListSrc()->getNbParticles()){
                uassert(false);
                return;
            }

            if(octreeIterator.moveRight() == false){
                break;
            }

            uassert(octreeIteratorValide.moveRight() != false);
        }
    }



    /** This function tests the octree to be sure that the fmm algorithm
     * has worked completly.
     */
    template<class OctreeClass, class ContainerClass, class FmmClassProc>
    void ValidateFMMAlgoProc(OctreeClass* const badTree,
                             OctreeClass* const valideTree,
                             FmmClassProc* const fmm){
        const int OctreeHeight = badTree->getHeight();
        {
            typename OctreeClass::Iterator octreeIterator(badTree);
            octreeIterator.gotoBottomLeft();

            typename OctreeClass::Iterator octreeIteratorValide(valideTree);
            octreeIteratorValide.gotoBottomLeft();

            for(int level = OctreeHeight - 1 ; level > 0 && fmm->hasWorkAtLevel(level) ; --level){

                while(octreeIteratorValide.getCurrentGlobalIndex() != octreeIterator.getCurrentGlobalIndex()) {
                    octreeIteratorValide.moveRight();
                }

                while(octreeIteratorValide.getCurrentGlobalIndex() != fmm->getWorkingInterval(level).leftIndex){
                    octreeIteratorValide.moveRight();
                    octreeIterator.moveRight();
                }

                FSize countCheck = 0;
                do{
                    if(octreeIterator.getCurrentGlobalIndex() != octreeIteratorValide.getCurrentGlobalIndex()){
                        uassert(false);
                    }
                    else{
                        uassert(octreeIterator.getCurrentCell()->getDataUp() == octreeIteratorValide.getCurrentCell()->getDataUp());
                        uassert(octreeIterator.getCurrentCell()->getDataDown() == octreeIteratorValide.getCurrentCell()->getDataDown());
                    }
                    ++countCheck;
                } while(octreeIteratorValide.moveRight() && octreeIterator.moveRight());

                octreeIterator.moveUp();
                octreeIterator.gotoLeft();

                octreeIteratorValide.moveUp();
                octreeIteratorValide.gotoLeft();
            }
        }
        {
            FSize NbPart = 0;
            FSize NbLeafs = 0;
            {
                typename OctreeClass::Iterator octreeIterator(valideTree);
                octreeIterator.gotoBottomLeft();
                do{
                    NbPart += octreeIterator.getCurrentListSrc()->getNbParticles();
                    ++NbLeafs;
                } while(octreeIterator.moveRight());
            }
            {
                typename OctreeClass::Iterator octreeIterator(badTree);
                octreeIterator.gotoBottomLeft();

                do {
                    const bool isUsingTsm = (octreeIterator.getCurrentListTargets() != octreeIterator.getCurrentListSrc());

                    ContainerClass* container = (octreeIterator.getCurrentListTargets());
                    const long long int*const dataDown = container->getDataDown();

                    for(FSize idxPart = 0 ; idxPart < container->getNbParticles() ; ++idxPart){
                        uassert((!isUsingTsm && dataDown[idxPart] == NbPart - 1) || (isUsingTsm && dataDown[idxPart] == NbPart));
                    }
                } while( octreeIterator.moveRight());
            }
        }
        {
            {
                // Check that each particle has been summed with all other
                typename OctreeClass::Iterator octreeIterator(badTree);
                octreeIterator.gotoBottomLeft();

                do {
                    uassert(octreeIterator.getCurrentListSrc()->getNbParticles() == octreeIterator.getCurrentCell()->getDataUp());
                } while( octreeIterator.moveRight() );
            }
        }
        {
            typename OctreeClass::Iterator octreeIterator(badTree);
            octreeIterator.gotoBottomLeft();

            typename OctreeClass::Iterator valideOctreeIterator(valideTree);
            valideOctreeIterator.gotoBottomLeft();
            while(valideOctreeIterator.getCurrentGlobalIndex() != octreeIterator.getCurrentGlobalIndex()){
                valideOctreeIterator.moveRight();
            }

            do {
                if(valideOctreeIterator.getCurrentGlobalIndex() != octreeIterator.getCurrentGlobalIndex()){
                    uassert(false);
                    break;
                }

                if(octreeIterator.getCurrentListTargets()->getNbParticles() != valideOctreeIterator.getCurrentListTargets()->getNbParticles()){
                    uassert(false);
                }
                else {
                    ContainerClass* container = (octreeIterator.getCurrentListTargets());
                    const long long int*const dataDown = container->getDataDown();

                    ContainerClass* containerValide = (valideOctreeIterator.getCurrentListTargets());
                    const long long int*const dataDownValide = containerValide->getDataDown();

190
                    for(FSize idxPart = 0 ; idxPart < container->getNbParticles() ; ++idxPart){
191 192 193 194 195 196 197 198
                        uassert(dataDown[idxPart] == dataDownValide[idxPart]);
                    }
                }

            }while( octreeIterator.moveRight() && valideOctreeIterator.moveRight());
        }
    }

199
    typedef double FReal;
200
    typedef FTestCell                  CellClass;
201
    typedef FTestParticleContainer<FReal>     ContainerClass;
202

203 204
    typedef FSimpleLeaf<FReal, ContainerClass >                     LeafClass;
    typedef FOctree<FReal, CellClass, ContainerClass , LeafClass >  OctreeClass;
205 206 207 208 209 210 211 212 213 214
    typedef FTestKernels< CellClass, ContainerClass >         KernelClass;

    typedef FFmmAlgorithmThread<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass >     FmmClass;
    typedef FFmmAlgorithmThreadProc<OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass >     FmmClassProc;


    void TestAlgo(){
        const int NbLevels = 7;
        const int SizeSubLevels = 3;
        const char* const filename = "../../Data/unitCubeXYZQ20k.bfma";
215
        FMpiFmaGenericLoader<FReal> loader(filename,app.global());
216 217 218 219 220

        OctreeClass realTree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox());

        if( app.global().processCount() != 1){
            struct TestParticle{
221 222
                FPoint<FReal> position;
                const FPoint<FReal>& getPosition(){
223 224 225 226 227 228 229
                    return position;
                }
            };

            TestParticle* particles = new TestParticle[loader.getNumberOfParticles()];
            memset(particles, 0, sizeof(TestParticle) * loader.getNumberOfParticles());
            FReal physicalValue;
230
            for(FSize idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
231 232 233 234 235
                loader.fillParticle(&particles[idxPart].position,&physicalValue);
            }

            FVector<TestParticle> finalParticles;
            FLeafBalance balancer;
236
            FMpiTreeBuilder< FReal,TestParticle >::DistributeArrayToContainer(app.global(),particles,
237 238 239 240 241 242 243 244 245 246 247
                                                                        loader.getMyNumberOfParticles(),
                                                                        realTree.getBoxCenter(),
                                                                        realTree.getBoxWidth(),realTree.getHeight(),
                                                                        &finalParticles, &balancer);
            for(int idx = 0 ; idx < finalParticles.getSize(); ++idx){
                realTree.insert(finalParticles[idx].position);
            }

            delete[] particles;
        }
        else{
248
            FPoint<FReal> position;
249 250 251 252 253 254 255 256 257 258
            FReal physicalValue;
            const FSize nbParticles = loader.getNumberOfParticles();
            for(FSize idxPart = 0 ; idxPart < nbParticles ; ++idxPart){
                loader.fillParticle(&position,&physicalValue);
                realTree.insert(position);
            }
        }

        OctreeClass treeValide(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox());
        {
259 260
            FFmaGenericLoader<FReal> loaderSeq(filename);
            FPoint<FReal> position;
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
            FReal physicalValue;
            for(FSize idxPart = 0 ; idxPart < loaderSeq.getNumberOfParticles() ; ++idxPart){
                loaderSeq.fillParticle(&position,&physicalValue);
                treeValide.insert(position);
            }
        }

        ValidateTree(realTree, treeValide);


        KernelClass kernels;
        FmmClassProc algo(app.global(),&realTree,&kernels);
        algo.execute();

        FmmClass algoValide(&treeValide,&kernels);
        algoValide.execute();

        ValidateFMMAlgoProc<OctreeClass,ContainerClass, FmmClassProc>(&realTree,&treeValide,&algo);
    }


    // set test
    void SetTests(){
        AddTest(&TestFmmAlgoProc::TestAlgo,"Test Algorithm");
    }
public:
    TestFmmAlgoProc(int argc,char ** argv) : FUTesterMpi(argc,argv){
    }
};

// You must do this
TestClassMpi(TestFmmAlgoProc)