From c96a506542561e7e4e607ebe79b4139af24a2def Mon Sep 17 00:00:00 2001 From: berenger-bramas <berenger-bramas@2616d619-271b-44dc-8df4-d4a8f33a7222> Date: Wed, 25 Jan 2012 14:02:00 +0000 Subject: [PATCH] Add some code to the new kernels to run for M2M L2L M2L for level inf than 0, need test git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/scalfmm/scalfmm/trunk@311 2616d619-271b-44dc-8df4-d4a8f33a7222 --- Src/Kernels/FElecForcesKernels.hpp | 141 +++++++++++++++++++++++++---- 1 file changed, 122 insertions(+), 19 deletions(-) diff --git a/Src/Kernels/FElecForcesKernels.hpp b/Src/Kernels/FElecForcesKernels.hpp index bd14ab064..dca99c92b 100644 --- a/Src/Kernels/FElecForcesKernels.hpp +++ b/Src/Kernels/FElecForcesKernels.hpp @@ -25,13 +25,22 @@ class FElecForcesKernels : public FAbstractKernels<ParticleClass,CellClass,Conta const FReal boxWidth; //< the box width at leaf level const int treeHeight; //< The height of the tree + const int periodicLevels; //< The number of levels above 1 used for periodicity + FHarmonic harmonic; //< The harmonic computation class + // For normal computation FComplexe* preL2LTransitions; //< The pre-computation for the L2L based on the level FComplexe* preM2MTransitions; //< The pre-computation for the M2M based on the level FComplexe* preM2LTransitions; //< The pre-computation for the M2L based on the level and the 189 possibilities + // For harmonic computation + FComplexe* preL2LTransitionsPer; //< The pre-computation for the L2L based on the level + FComplexe* preM2MTransitionsPer; //< The pre-computation for the M2M based on the level + + FComplexe* preM2LTransitionsPer; //< The pre-computation for the M2L based on the level and the 189 possibilities + /** To access te preL2L/preM2M right vector */ int indexTransition(const int level, const int child){ return level * 8 * harmonic.getExpSize() + child * harmonic.getExpSize(); @@ -96,24 +105,83 @@ class FElecForcesKernels : public FAbstractKernels<ParticleClass,CellClass,Conta } } + void allocAndInitPer(){ + if( periodicLevels ){ + preL2LTransitionsPer = new FComplexe[periodicLevels * 8 * harmonic.getExpSize()]; + preM2MTransitionsPer = new FComplexe[periodicLevels * 8 * harmonic.getExpSize()]; + + FReal treeWidthAtLevel = boxWidth; + for(int idxLevel = -1 ; idxLevel <= -periodicLevels ; --idxLevel ){ + const F3DPosition father(treeWidthAtLevel,treeWidthAtLevel,treeWidthAtLevel); + treeWidthAtLevel *= 2; + + for(int idxChild = 0 ; idxChild < 8 ; ++idxChild ){ + FTreeCoordinate childBox; + childBox.setPositionFromMorton(idxChild,1); + + const F3DPosition M2MVector ( + father.getX() - (treeWidthAtLevel * FReal(1 + (childBox.getX() * 2))), + father.getY() - (treeWidthAtLevel * FReal(1 + (childBox.getY() * 2))), + father.getZ() - (treeWidthAtLevel * FReal(1 + (childBox.getZ() * 2))) + ); + + harmonic.computeInner(FSpherical(M2MVector)); + FMemUtils::copyall<FComplexe>(&preM2MTransitionsPre[indexTransition(-1-idxLevel,idxChild)], harmonic.result(), harmonic.getExpSize()); + + const F3DPosition L2LVector ( + (treeWidthAtLevel * FReal(1 + (childBox.getX() * 2))) - father.getX(), + (treeWidthAtLevel * FReal(1 + (childBox.getY() * 2))) - father.getY(), + (treeWidthAtLevel * FReal(1 + (childBox.getZ() * 2))) - father.getZ() + ); + + harmonic.computeInner(FSpherical(L2LVector)); + FMemUtils::copyall<FComplexe>(&preL2LTransitionsPre[indexTransition(-1-idxLevel,idxChild)], harmonic.result(), harmonic.getExpSize()); + } + } + + // M2L transfer, there is a maximum of 3 neighbors in each direction, + // so 6 in each dimension + treeWidthAtLevel = boxWidth*2; + preM2LTransitionsPer = new FComplexe[periodicLevels * (7 * 7 * 7) * devM2lP]; + for(int idxLevel = -1 ; idxLevel <= -periodicLevels ; --idxLevel ){ + for(int idxX = -3 ; idxX <= 3 ; ++idxX ){ + for(int idxY = -3 ; idxY <= 3 ; ++idxY ){ + for(int idxZ = -3 ; idxZ <= 3 ; ++idxZ ){ + if(idxX || idxY || idxZ){ + const F3DPosition relativePos( FReal(idxX) * treeWidthAtLevel , FReal(idxY) * treeWidthAtLevel , FReal(idxZ) * treeWidthAtLevel ); + harmonic.computeOuter(FSpherical(relativePos)); + FMemUtils::copyall<FComplexe>(&preM2LTransitionsPre[indexM2LTransition(-1-idxLevel,idxX,idxY,idxZ)], harmonic.result(), harmonic.getExpSize()); + } + } + } + } + treeWidthAtLevel *= 2; + } + } + } + public: /** Kernel constructor */ - FElecForcesKernels(const int inDevP, const int inTreeHeight, const FReal inBoxWidth) + FElecForcesKernels(const int inDevP, const int inTreeHeight, const FReal inBoxWidth, const int inPeriodicLevel = 0) : devP(inDevP), devM2lP(int(((inDevP*2)+1) * ((inDevP*2)+2) * 0.5)), boxWidth(inBoxWidth), - treeHeight(inTreeHeight), harmonic(inDevP), - preL2LTransitions(0), preM2MTransitions(0), preM2LTransitions(0) { + treeHeight(inTreeHeight), periodicLevels(inPeriodicLevel), harmonic(inDevP), + preL2LTransitions(0), preM2MTransitions(0), preM2LTransitions(0), + preL2LTransitionsPer(0), preM2MTransitionsPer(0), preM2LTransitionsPer(0) { allocAndInit(); + allocAndInitPer(); } /** Copy constructor */ FElecForcesKernels(const FElecForcesKernels& other) : devP(other.devP), devM2lP(other.devM2lP), boxWidth(other.boxWidth), - treeHeight(other.boxWidth), harmonic(other.devP), - preL2LTransitions(0), preM2MTransitions(0), preM2LTransitions(0) { + treeHeight(other.boxWidth), periodicLevels(other.periodicLevels), harmonic(other.devP), + preL2LTransitions(0), preM2MTransitions(0), preM2LTransitions(0), + preL2LTransitionsPer(0), preM2MTransitionsPer(0), preM2LTransitionsPer(0) { allocAndInit(); + allocAndInitPer(); } /** Default destructor */ @@ -121,6 +189,10 @@ public: delete[] preL2LTransitions; delete[] preM2MTransitions; delete[] preM2LTransitions; + + delete[] preL2LTransitionsPer; + delete[] preM2MTransitionsPer; + delete[] preM2LTransitionsPer; } /** P2M with a cell and all its particles */ @@ -141,9 +213,18 @@ public: void M2M(CellClass* const FRestrict inPole, const CellClass *const FRestrict *const FRestrict inChild, const int inLevel) { FComplexe* const multipole_exp_target = inPole->getMultipole(); // iter on each child and process M2M - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - if(inChild[idxChild]){ - multipoleToMultipole(multipole_exp_target, inChild[idxChild]->getMultipole(), &preM2MTransitions[indexTransition(inLevel,idxChild)]); + if( level >= 0){ + for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ + if(inChild[idxChild]){ + multipoleToMultipole(multipole_exp_target, inChild[idxChild]->getMultipole(), &preM2MTransitions[indexTransition(inLevel,idxChild)]); + } + } + } + else{ + for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ + if(inChild[idxChild]){ + multipoleToMultipole(multipole_exp_target, inChild[idxChild]->getMultipole(), &preM2MTransitionsPer[indexTransition(-1-inLevel,idxChild)]); + } } } } @@ -153,23 +234,45 @@ public: const int size, const int inLevel) { const FTreeCoordinate& coordCenter = pole->getCoordinate(); // For all neighbors compute M2L - for(int idxNeigh = 0 ; idxNeigh < size ; ++idxNeigh){ - const FTreeCoordinate& coordNeighbors = distantNeighbors[idxNeigh]->getCoordinate(); - const FComplexe* const transitionVector = &preM2LTransitions[indexM2LTransition(inLevel, - (coordCenter.getX() - coordNeighbors.getX()), - (coordCenter.getY() - coordNeighbors.getY()), - (coordCenter.getZ() - coordNeighbors.getZ()))]; - - multipoleToLocal(pole->getLocal(), distantNeighbors[idxNeigh]->getMultipole(), transitionVector); + if( inLevel >= 0){ + for(int idxNeigh = 0 ; idxNeigh < size ; ++idxNeigh){ + const FTreeCoordinate& coordNeighbors = distantNeighbors[idxNeigh]->getCoordinate(); + const FComplexe* const transitionVector = &preM2LTransitions[indexM2LTransition(inLevel, + (coordCenter.getX() - coordNeighbors.getX()), + (coordCenter.getY() - coordNeighbors.getY()), + (coordCenter.getZ() - coordNeighbors.getZ()))]; + + multipoleToLocal(pole->getLocal(), distantNeighbors[idxNeigh]->getMultipole(), transitionVector); + } + } + else { + for(int idxNeigh = 0 ; idxNeigh < size ; ++idxNeigh){ + const FTreeCoordinate& coordNeighbors = distantNeighbors[idxNeigh]->getCoordinate(); + const FComplexe* const transitionVector = &preM2LTransitionsPer[indexM2LTransition(-1-inLevel, + (coordCenter.getX() - coordNeighbors.getX()), + (coordCenter.getY() - coordNeighbors.getY()), + (coordCenter.getZ() - coordNeighbors.getZ()))]; + + multipoleToLocal(pole->getLocal(), distantNeighbors[idxNeigh]->getMultipole(), transitionVector); + } } } /** L2L with a cell and all its child */ void L2L(const CellClass* const FRestrict pole, CellClass* FRestrict *const FRestrict child, const int inLevel) { // iter on each child and process L2L - for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ - if(child[idxChild]){ - localToLocal(child[idxChild]->getLocal(), pole->getLocal(), &preL2LTransitions[indexTransition(inLevel,idxChild)]); + if( inLevel >= 0){ + for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ + if(child[idxChild]){ + localToLocal(child[idxChild]->getLocal(), pole->getLocal(), &preL2LTransitions[indexTransition(inLevel,idxChild)]); + } + } + } + else{ + for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ + if(child[idxChild]){ + localToLocal(child[idxChild]->getLocal(), pole->getLocal(), &preL2LTransitionsPer[indexTransition(-1-inLevel,idxChild)]); + } } } } -- GitLab