FTestKernels.hpp 6.74 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
#ifndef FTESTKERNELS_HPP
#define FTESTKERNELS_HPP
13

14 15 16 17 18

#include <iostream>

#include "FAbstractKernels.hpp"
#include "../Containers/FOctree.hpp"
19
#include "../Utils/FGlobal.hpp"
20 21 22 23 24 25 26 27 28 29 30 31
#include "../Utils/FTrace.hpp"

/**
* @author Berenger Bramas (berenger.bramas@inria.fr)
* @class AbstractKernels
* @brief
* Please read the license
*
* This kernels is a virtual kernels to validate that the fmm algorithm is
* correctly done on particles.
* It used FTestCell and FTestParticle
*/
berenger-bramas's avatar
berenger-bramas committed
32
template< class ParticleClass, class CellClass, class ContainerClass>
33
class FTestKernels {
34 35 36 37 38
public:
    /** Default destructor */
    virtual ~FTestKernels(){
    }

berenger-bramas's avatar
berenger-bramas committed
39
    /** Before upward */
berenger-bramas's avatar
berenger-bramas committed
40
    void P2M(CellClass* const pole, const ContainerClass* const particles) {
41

42
        // the pole represents all particles under
43
        pole->setDataUp(pole->getDataUp() + particles->getSize());
44
    }
berenger-bramas's avatar
berenger-bramas committed
45

berenger-bramas's avatar
berenger-bramas committed
46
    /** During upward */
47
    void M2M(CellClass* const FRestrict pole, const CellClass *const FRestrict *const FRestrict child, const int /*level*/) {
48

49 50 51 52 53 54 55
        // A parent represents the sum of the child
        for(int idx = 0 ; idx < 8 ; ++idx){
            if(child[idx]){
                pole->setDataUp(pole->getDataUp() + child[idx]->getDataUp());
            }
        }
    }
berenger-bramas's avatar
berenger-bramas committed
56

berenger-bramas's avatar
berenger-bramas committed
57
    /** Before Downward */
58
    void M2L(CellClass* const FRestrict pole, const CellClass* distantNeighbors[343], const int /*size*/, const int /*level*/) {
59

60
        // The pole is impacted by what represent other poles
61
        for(int idx = 0 ; idx < 343 ; ++idx){
62 63 64
            if(distantNeighbors[idx]){
                pole->setDataDown(pole->getDataDown() + distantNeighbors[idx]->getDataUp());
            }
65 66
        }
    }
berenger-bramas's avatar
berenger-bramas committed
67

berenger-bramas's avatar
berenger-bramas committed
68
    /** During Downward */
69
    void L2L(const CellClass*const FRestrict local, CellClass* FRestrict *const FRestrict child, const int /*level*/) {
70

71 72 73 74 75 76
        // Each child is impacted by the father
        for(int idx = 0 ; idx < 8 ; ++idx){
            if(child[idx]){
                child[idx]->setDataDown(local->getDataDown() + child[idx]->getDataDown());
            }
        }
77

78
    }
berenger-bramas's avatar
berenger-bramas committed
79

berenger-bramas's avatar
berenger-bramas committed
80
    /** After Downward */
berenger-bramas's avatar
berenger-bramas committed
81
    void L2P(const CellClass* const  local, ContainerClass*const particles){
82

83
        // The particles is impacted by the parent cell
berenger-bramas's avatar
berenger-bramas committed
84
        typename ContainerClass::BasicIterator iter(*particles);
berenger-bramas's avatar
berenger-bramas committed
85 86
        while( iter.hasNotFinished() ){
            iter.data().setDataDown(iter.data().getDataDown() + local->getDataDown());
berenger-bramas's avatar
berenger-bramas committed
87
            iter.gotoNext();
88
        }
89

90
    }
berenger-bramas's avatar
berenger-bramas committed
91 92


berenger-bramas's avatar
berenger-bramas committed
93
    /** After Downward */
berenger-bramas's avatar
berenger-bramas committed
94 95 96
    void P2P(const FTreeCoordinate& ,
                 ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict sources,
                 ContainerClass* const directNeighborsParticles[27], const int ){
97

berenger-bramas's avatar
berenger-bramas committed
98
        // Each particles targeted is impacted by the particles sources
99
        long long int inc = sources->getSize();
berenger-bramas's avatar
berenger-bramas committed
100 101 102
        if(targets == sources){
            inc -= 1;
        }
berenger-bramas's avatar
berenger-bramas committed
103 104 105 106
        for(int idx = 0 ; idx < 27 ; ++idx){
            if( directNeighborsParticles[idx] ){
                inc += directNeighborsParticles[idx]->getSize();
            }
berenger-bramas's avatar
berenger-bramas committed
107 108
        }

berenger-bramas's avatar
berenger-bramas committed
109
        typename ContainerClass::BasicIterator iter(*targets);
berenger-bramas's avatar
berenger-bramas committed
110 111
        while( iter.hasNotFinished() ){
            iter.data().setDataDown(iter.data().getDataDown() + inc);
berenger-bramas's avatar
berenger-bramas committed
112
            iter.gotoNext();
berenger-bramas's avatar
berenger-bramas committed
113
        }
114

berenger-bramas's avatar
berenger-bramas committed
115
    }
116 117 118 119 120 121
};


/** This function test the octree to be sure that the fmm algorithm
  * has worked completly.
  */
berenger-bramas's avatar
berenger-bramas committed
122 123
template< class OctreeClass, class ParticleClass, class CellClass, class ContainerClass, class LeafClass>
void ValidateFMMAlgo(OctreeClass* const tree){
124
    std::cout << "Check Result\n";
125
    const int TreeHeight = tree->getHeight();
126
    long long int NbPart = 0;
127
    { // Check that each particle has been summed with all other
berenger-bramas's avatar
berenger-bramas committed
128
        typename OctreeClass::Iterator octreeIterator(tree);
129 130 131 132 133 134 135 136 137
        octreeIterator.gotoBottomLeft();
        do{
            if(octreeIterator.getCurrentCell()->getDataUp() != octreeIterator.getCurrentListSrc()->getSize() ){
                    std::cout << "Problem P2M : " << (octreeIterator.getCurrentCell()->getDataUp() - octreeIterator.getCurrentListSrc()->getSize()) << "\n";
            }
            NbPart += octreeIterator.getCurrentListSrc()->getSize();
        } while(octreeIterator.moveRight());
    }
    { // Ceck if there is number of NbPart summed at level 1
berenger-bramas's avatar
berenger-bramas committed
138
        typename OctreeClass::Iterator octreeIterator(tree);
139
        octreeIterator.moveDown();
140
        long long int res = 0;
141 142 143 144 145 146 147 148
        do{
            res += octreeIterator.getCurrentCell()->getDataUp();
        } while(octreeIterator.moveRight());
        if(res != NbPart){
            std::cout << "Problem M2M at level 1 : " << res << "\n";
        }
    }
    { // Ceck if there is number of NbPart summed at level 1
berenger-bramas's avatar
berenger-bramas committed
149
        typename OctreeClass::Iterator octreeIterator(tree);
150 151
        octreeIterator.gotoBottomLeft();
        for(int idxLevel = TreeHeight - 1 ; idxLevel > 1 ; --idxLevel ){
152
            long long int res = 0;
153 154 155 156 157 158 159 160 161 162 163
            do{
                res += octreeIterator.getCurrentCell()->getDataUp();
            } while(octreeIterator.moveRight());
            if(res != NbPart){
                std::cout << "Problem M2M at level " << idxLevel << " : " << res << "\n";
            }
            octreeIterator.moveUp();
            octreeIterator.gotoLeft();
        }
    }
    { // Check that each particle has been summed with all other
berenger-bramas's avatar
berenger-bramas committed
164
        typename OctreeClass::Iterator octreeIterator(tree);
165 166
        octreeIterator.gotoBottomLeft();
        do{
berenger-bramas's avatar
berenger-bramas committed
167
            typename ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListTargets());
168 169 170

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

berenger-bramas's avatar
berenger-bramas committed
171
            while( iter.hasNotFinished() ){
172 173
                // If a particles has been impacted by less than NbPart - 1 (the current particle)
                // there is a problem
berenger-bramas's avatar
berenger-bramas committed
174 175 176
                if( (!isUsingTsm && iter.data().getDataDown() != NbPart - 1) ||
                    (isUsingTsm && iter.data().getDataDown() != NbPart) ){
                    std::cout << "Problem L2P + P2P : " << iter.data().getDataDown() << "\n";
177
                }
berenger-bramas's avatar
berenger-bramas committed
178
                iter.gotoNext();
179 180 181 182 183 184 185 186 187 188 189
            }
        } while(octreeIterator.moveRight());
    }

    std::cout << "Done\n";
}



#endif //FTESTKERNELS_HPP

190