Mentions légales du service

Skip to content
Snippets Groups Projects
testFmmAlgorithmProcPeriodic.cpp 11.86 KiB
// See LICENCE file at project root

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

#include <iostream>

#include <cstdio>
#include <cstdlib>

#include "Utils/FParameters.hpp"
#include "Utils/FTic.hpp"

#include "Containers/FOctree.hpp"
#include "Containers/FVector.hpp"

#include "Components/FSimpleLeaf.hpp"
#include "Files/FRandomLoader.hpp"

#include "Utils/FPoint.hpp"

#include "Components/FTestParticleContainer.hpp"
#include "Components/FTestCell.hpp"
#include "Components/FTestKernels.hpp"

#include "Core/FFmmAlgorithmPeriodic.hpp"
#include "Core/FFmmAlgorithmThreadProcPeriodic.hpp"

#include "Files/FMpiTreeBuilder.hpp"

#include "Utils/FLeafBalance.hpp"

#include "Utils/FParameterNames.hpp"

/** This program show an example of use of
  * the fmm basic algo
  * it also check that each particles is impacted each other particles
  */


// Simply create particles and try the kernels
int main(int argc, char ** argv){
    FHelpDescribeAndExit(argc, argv,
                         "Test FMM periodic distributed algorithm by counting the nb of interactions each particle receive.",
                         FParameterDefinitions::OctreeHeight, FParameterDefinitions::OctreeSubHeight,
                         FParameterDefinitions::NbParticles);

    typedef double FReal;

    typedef FTestCell                   CellClass;
    typedef FTestParticleContainer<FReal>      ContainerClass;

    typedef FSimpleLeaf<FReal, ContainerClass >                     LeafClass;
    typedef FOctree<FReal, CellClass, ContainerClass , LeafClass >  OctreeClass;
    typedef FTestKernels< CellClass, ContainerClass >         KernelClass;

    typedef FFmmAlgorithmThreadProcPeriodic<FReal, OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass >     FmmClass;
    typedef FFmmAlgorithmPeriodic<FReal, OctreeClass, CellClass, ContainerClass, KernelClass, LeafClass >     FmmClassSeq;
    ///////////////////////What we do/////////////////////////////
    std::cout << ">> This executable has to be used to test the FMM algorithm.\n";
    //////////////////////////////////////////////////////////////

    const int NbLevels          = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeHeight.options, 7);
    const int SizeSubLevels     = FParameters::getValue(argc,argv,FParameterDefinitions::OctreeSubHeight.options, 3);
    const long NbParticles      = FParameters::getValue(argc,argv,FParameterDefinitions::NbParticles.options, 5);
    const int PeriodicDeep      = FParameters::getValue(argc,argv,"-per", 2);


    FMpi app(argc, argv);

    FTic counter;

    //////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////

    std::cout << "Creating & Inserting " << NbParticles << " particles per boxes ..." << std::endl;
    std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl;
    counter.tic();

    FRandomLoader<FReal> loader(NbParticles,FReal(1.0),FPoint<FReal>(0,0,0), app.global().processId());
    OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox());

    {
        struct TestParticle{
            FPoint<FReal> position;
            const FPoint<FReal>& getPosition(){
                return position;
            }
        };

        TestParticle*const particles = new TestParticle[NbParticles];

        for(int idx = 0 ; idx < NbParticles ; ++idx){
            loader.fillParticle(&particles[idx].position);
        }

        FVector<TestParticle> finalParticles;
        FLeafBalance balancer;

        FMpiTreeBuilder< FReal,TestParticle >::DistributeArrayToContainer(app.global(),particles,
                                                                    NbParticles,
                                                                    loader.getCenterOfBox(),
                                                                    loader.getBoxWidth(),tree.getHeight(),
                                                                    &finalParticles, &balancer);

        for(int idx = 0 ; idx < finalParticles.getSize(); ++idx){
            tree.insert(finalParticles[idx].position);
        }
        delete[] particles;
    }

    counter.tac();
    std::cout << "Done  " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl;

    //////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////

    std::cout << "Working on particles ..." << std::endl;
    counter.tic();

    KernelClass kernels;
    FmmClass algo( app.global(), &tree, PeriodicDeep);
    algo.setKernel(&kernels);
    algo.execute();

    counter.tac();
    std::cout << "Done  " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl;

    //////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////

    {
        long long totalRepeatedBox = algo.theoricalRepetition();
        std::cout << "totalRepeatedBox in each dim is = " << totalRepeatedBox << "\n";
        totalRepeatedBox = (totalRepeatedBox*totalRepeatedBox*totalRepeatedBox);
        const long long NbParticlesEntireSystem = (NbParticles * app.global().processCount()) * totalRepeatedBox;
        std::cout << "The total number of particles is "  << NbParticlesEntireSystem << "\n";
        FTreeCoordinate min, max;
        algo.repetitionsIntervals(&min, &max);
        std::cout << "Min is " << min << " Max is " << max << std::endl;

        OctreeClass::Iterator octreeIterator(&tree);
        octreeIterator.gotoBottomLeft();
        do{
            ContainerClass* container = (octreeIterator.getCurrentListTargets());
            const long long int*const dataDown = container->getDataDown();

            for(FSize idxPart = 0 ; idxPart < container->getNbParticles() ; ++idxPart){
                if( NbParticlesEntireSystem - 1 != dataDown[idxPart]){
                    std::cout << "P2P probleme, should be " << NbParticlesEntireSystem - 1 <<
                                 " iter.data().getDataDown() "<< dataDown[idxPart] << std::endl;
                }
            }
        } while(octreeIterator.moveRight());
    }

    //////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////

    {
        OctreeClass treeSeq(NbLevels, SizeSubLevels, FReal(1.0), FPoint<FReal>(0,0,0));
        for(int idx = 0 ; idx < app.global().processCount() ; ++idx ){
            FPoint<FReal> position;
            FRandomLoader<FReal> loaderSeq(NbParticles,FReal(1.0),FPoint<FReal>(0,0,0), idx);
            for(FSize idxPart = 0 ; idxPart < loaderSeq.getNumberOfParticles() ; ++idxPart){
                loaderSeq.fillParticle(&position);
                treeSeq.insert(position);
            }
        }

        FmmClassSeq algoSeq( &treeSeq, PeriodicDeep);
        algoSeq.setKernel(&kernels);
        algoSeq.execute();

        { // Ceck if there is number of NbPart summed at level 1
            typename OctreeClass::Iterator octreeIterator(&tree);
            octreeIterator.gotoBottomLeft();

            typename OctreeClass::Iterator octreeIteratorSeq(&treeSeq);
            octreeIteratorSeq.gotoBottomLeft();

            for(int idxLevel = tree.getHeight() - 1 ; idxLevel >= 1 ; --idxLevel ){
                std::cout << "Process level " << idxLevel << std::endl;

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

                do{
                    if( octreeIterator.getCurrentGlobalIndex() != octreeIteratorSeq.getCurrentGlobalIndex()){
                        std::cout << "Index problem !!!!!" << std::endl;
                    }

                    if( algo.getWorkingInterval(idxLevel).leftIndex <= octreeIteratorSeq.getCurrentGlobalIndex()){
                        if( octreeIterator.getCurrentCell()->getDataUp() != octreeIteratorSeq.getCurrentCell()->getDataUp() ){
                            std::cout << "Up problem at " << octreeIterator.getCurrentGlobalIndex() <<
                                         " Good is " << octreeIteratorSeq.getCurrentCell()->getDataUp() <<
                                         " Bad is " << octreeIterator.getCurrentCell()->getDataUp() << std::endl;
                        }
                        if( octreeIterator.getCurrentCell()->getDataDown() != octreeIteratorSeq.getCurrentCell()->getDataDown() ){
                            std::cout << "Down problem at " << octreeIterator.getCurrentGlobalIndex() <<
                                         " Good is " << octreeIteratorSeq.getCurrentCell()->getDataDown() <<
                                         " Bad is " << octreeIterator.getCurrentCell()->getDataDown() << std::endl;
                        }
                    }
                } while(octreeIterator.moveRight() && octreeIteratorSeq.moveRight());

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

                octreeIteratorSeq.moveUp();
                octreeIteratorSeq.gotoLeft();
            }
        }
        { // Check that each particle has been summed with all other
            typename OctreeClass::Iterator octreeIterator(&tree);
            octreeIterator.gotoBottomLeft();

            typename OctreeClass::Iterator octreeIteratorSeq(&treeSeq);
            octreeIteratorSeq.gotoBottomLeft();


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

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

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

                if( octreeIterator.getCurrentGlobalIndex() != octreeIteratorSeq.getCurrentGlobalIndex()){
                    std::cout << "Index problem !!!!!" << std::endl;
                }

                if(container->getNbParticles() != containerValide->getNbParticles()){
                    std::cout << "Not the same number of particles on the leaf " << octreeIterator.getCurrentGlobalIndex() << "\n";
                    std::cout << "\t Correct is " << containerValide->getNbParticles() << "\n";
                    std::cout << "\t Not Correct is " << container->getNbParticles() << "\n";
                }

                for(FSize idxPart = 0 ; idxPart < container->getNbParticles() ; ++idxPart){
                    // If a particles has been impacted by less than NbPart - 1 (the current particle)
                    // there is a problem
                    if( dataDown[idxPart] != dataDownValide[idxPart]){
                        std::cout << "Problem on leaf " << octreeIterator.getCurrentGlobalIndex() <<
                                     " part " << idxPart << " valide data down " << dataDownValide[idxPart] <<
                                     " invalide " << dataDown[idxPart] << "\n";
                        std::cout << "Data down for leaf is: valide " << octreeIteratorSeq.getCurrentCell()->getDataDown()
                                  << " invalide " << octreeIterator.getCurrentCell()->getDataDown()
                                  << " size is: valide " <<  octreeIteratorSeq.getCurrentListTargets()->getNbParticles()
                                  << " invalide " << octreeIterator.getCurrentListTargets()->getNbParticles() << std::endl;
                    }
                }
            } while(octreeIterator.moveRight() && octreeIteratorSeq.moveRight());
        }
    }
    std::cout << "Test is over...\n";

    return 0;
}