Attention une mise à jour du serveur va être effectuée le vendredi 16 avril entre 12h et 12h30. Cette mise à jour va générer une interruption du service de quelques minutes.

Commit 088fbae5 authored by BLANCHARD Pierre's avatar BLANCHARD Pierre

Fixed Uniform FMAlgoThread (FFT implementation is not thread safe), some cleanup.

parent bb443606
#include "FInterpMatrixKernel.hpp"
/// ID_OVER_R
const unsigned int FInterpMatrixKernel_IOR::indexTab[]={0,0,0,1,1,2,
0,1,2,1,2,2};
const unsigned int FInterpMatrixKernel_IOR::applyTab[]={0,1,2,
1,3,4,
2,4,5};
/// R_IJ
const unsigned int FInterpMatrixKernel_R_IJ::indexTab[]={0,0,0,1,1,2,
0,1,2,1,2,2};
......
......@@ -27,7 +27,6 @@
enum KERNEL_FUNCTION_IDENTIFIER {ONE_OVER_R,
ONE_OVER_R_SQUARED,
LENNARD_JONES_POTENTIAL,
ID_OVER_R,
R_IJ,
R_IJK};
......@@ -68,7 +67,7 @@ struct FInterpAbstractMatrixKernel : FNoCopyable
/// One over r
struct FInterpMatrixKernelR : FInterpAbstractMatrixKernel
{
static const KERNEL_FUNCTION_TYPE Type = /*NON_*/HOMOGENEOUS;
static const KERNEL_FUNCTION_TYPE Type = HOMOGENEOUS;
static const KERNEL_FUNCTION_IDENTIFIER Identifier = ONE_OVER_R;
static const unsigned int NCMP = 1; //< number of components
static const unsigned int NPV = 1; //< dim of physical values
......@@ -106,18 +105,6 @@ struct FInterpMatrixKernelR : FInterpAbstractMatrixKernel
return FReal(2.) / CellWidth;
}
// FReal getScaleFactor(const FReal, const int) const
// {
// // return 1 because non homogeneous kernel functions cannot be scaled!!!
// return FReal(1.);
// }
//
// FReal getScaleFactor(const FReal) const
// {
// // return 1 because non homogeneous kernel functions cannot be scaled!!!
// return FReal(1.);
// }
};
......@@ -160,7 +147,7 @@ struct FInterpMatrixKernelRR : FInterpAbstractMatrixKernel
FReal getScaleFactor(const FReal CellWidth) const
{
return FReal(4.) / CellWidth;
return FReal(4.) / (CellWidth*CellWidth);
}
};
......@@ -241,80 +228,6 @@ struct FInterpMatrixKernelLJ : FInterpAbstractMatrixKernel
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// Test Tensorial kernel 1/R*Id_3
struct FInterpMatrixKernel_IOR : FInterpAbstractMatrixKernel
{
static const KERNEL_FUNCTION_TYPE Type = /*NON_*/HOMOGENEOUS;
static const KERNEL_FUNCTION_IDENTIFIER Identifier = ID_OVER_R;
static const unsigned int NK = 3*3; //< total number of components
static const unsigned int NCMP = 6; //< number of components after symmetry
static const unsigned int NPV = 3; //< dim of physical values
static const unsigned int NPOT = 3; //< dim of potentials
static const unsigned int NRHS = NPV; //< dim of mult exp
static const unsigned int NLHS = NPOT*NRHS; //< dim of loc exp
// store indices (i,j) corresponding to sym idx
static const unsigned int indexTab[/*2*NCMP=12*/];
// store positions in sym tensor
static const unsigned int applyTab[/*9*/];
const unsigned int _i,_j;
FInterpMatrixKernel_IOR(const double = 0.0, const unsigned int d = 0)
: _i(indexTab[d]), _j(indexTab[d+NCMP])
{}
// returns position in reduced storage from position in full 3x3 matrix
unsigned int getPosition(const unsigned int n) const
{return applyTab[n];}
FReal evaluate(const FPoint& x, const FPoint& y) const
{
const FPoint xy(x-y);
// low rank approx does not support nul kernels
// if(_i==_j)
return FReal(1.)/xy.norm();
// else
// return FReal(0.);
}
void evaluateBlock(const FPoint& x, const FPoint& y, FReal* block) const
{
const FPoint xy(x-y);
const FReal one_over_r = FReal(1.)/xy.norm();
for(unsigned int d=0;d<NCMP;++d){
// unsigned int i = indexTab[d];
// unsigned int j = indexTab[d+NCMP];
// if(i==j)
block[d] = one_over_r;
// else
// block[d] = 0.0;
}
}
FReal getScaleFactor(const FReal RootCellWidth, const int TreeLevel) const
{
const FReal CellWidth(RootCellWidth / FReal(FMath::pow(2, TreeLevel)));
return getScaleFactor(CellWidth);
}
FReal getScaleFactor(const FReal CellWidth) const
{
return FReal(2.) / CellWidth;
}
// FReal getScaleFactor(const FReal) const
// {
// // return 1 because non homogeneous kernel functions cannot be scaled!!!
// return FReal(1.);
// }
};
/// R_{,ij}
// PB: IMPORTANT! This matrix kernel does not present the symmetries
......@@ -413,12 +326,6 @@ struct FInterpMatrixKernel_R_IJ : FInterpAbstractMatrixKernel
return FReal(2.) / CellWidth;
}
// // R_{,ij} is set non-homogeneous
// FReal getScaleFactor(const FReal CellWidth) const
// {
// return FReal(1.);
// }
};
/// R_{,ijk}
......@@ -550,12 +457,6 @@ struct FInterpMatrixKernel_R_IJK : FInterpAbstractMatrixKernel
return FReal(4.) / (CellWidth*CellWidth);
}
// // R_{,ijk} is set non-homogeneous
// FReal getScaleFactor(const FReal CellWidth) const
// {
// return FReal(1.);
// }
};
......
......@@ -48,24 +48,6 @@ struct DirectInteractionComputer<LENNARD_JONES_POTENTIAL, 1>
}
};
/*! Specialization for ID_OVER_R potential */
template <>
struct DirectInteractionComputer<ID_OVER_R, 1>
{
template <typename ContainerClass>
static void P2P( ContainerClass* const FRestrict TargetParticles,
ContainerClass* const NeighborSourceParticles[27]){
FP2P::FullMutualIOR(TargetParticles,NeighborSourceParticles,14);
}
template <typename ContainerClass>
static void P2PRemote( ContainerClass* const FRestrict inTargets,
ContainerClass* const inNeighbors[27],
const int inSize){
FP2P::FullRemoteIOR(inTargets,inNeighbors,inSize);
}
};
/*! Specialization for GradGradR potential */
template <>
struct DirectInteractionComputer<R_IJ, 1>
......@@ -156,27 +138,6 @@ struct DirectInteractionComputer<LENNARD_JONES_POTENTIAL, NVALS>
}
};
/*! Specialization for ID_OVER_R potential */
template <int NVALS>
struct DirectInteractionComputer<ID_OVER_R, NVALS>
{
template <typename ContainerClass>
static void P2P( ContainerClass* const FRestrict TargetParticles,
ContainerClass* const NeighborSourceParticles[27]){
for(int idxRhs = 0 ; idxRhs < NVALS ; ++idxRhs){
FP2P::FullMutualIOR(TargetParticles,NeighborSourceParticles,14);
}
}
template <typename ContainerClass>
static void P2PRemote( ContainerClass* const FRestrict inTargets,
ContainerClass* const inNeighbors[27],
const int inSize){
for(int idxRhs = 0 ; idxRhs < NVALS ; ++idxRhs){
FP2P::FullRemoteIOR(inTargets,inNeighbors,inSize);
}
}
};
/*! Specialization for GradGradR potential */
template <int NVALS>
......
......@@ -1051,301 +1051,6 @@ namespace FP2P {
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// PB: Test Tensorial Kernel ID_over_R
// i.e. [[1 1 1]
// [1 1 1] * 1/R
// [1 1 1]]
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* @brief FullMutualIOR
*/
template <class ContainerClass>
inline void FullMutualIOR(ContainerClass* const FRestrict inTargets, ContainerClass* const inNeighbors[],
const int limiteNeighbors){
const int nbParticlesTargets = inTargets->getNbParticles();
const FReal*const targetsX = inTargets->getPositions()[0];
const FReal*const targetsY = inTargets->getPositions()[1];
const FReal*const targetsZ = inTargets->getPositions()[2];
for(int idxNeighbors = 0 ; idxNeighbors < limiteNeighbors ; ++idxNeighbors){
for(int idxTarget = 0 ; idxTarget < nbParticlesTargets ; ++idxTarget){
if( inNeighbors[idxNeighbors] ){
const int nbParticlesSources = inNeighbors[idxNeighbors]->getNbParticles();
const FReal*const sourcesX = inNeighbors[idxNeighbors]->getPositions()[0];
const FReal*const sourcesY = inNeighbors[idxNeighbors]->getPositions()[1];
const FReal*const sourcesZ = inNeighbors[idxNeighbors]->getPositions()[2];
for(int idxSource = 0 ; idxSource < nbParticlesSources ; ++idxSource){
FReal dx = sourcesX[idxSource] - targetsX[idxTarget];
FReal dy = sourcesY[idxSource] - targetsY[idxTarget];
FReal dz = sourcesZ[idxSource] - targetsZ[idxTarget];
FReal inv_distance_pow2 = FReal(1.0) / (dx*dx + dy*dy + dz*dz);
FReal inv_distance = FMath::Sqrt(inv_distance_pow2);
FReal inv_distance_pow3 = inv_distance_pow2 * inv_distance;
FReal r[3]={dx,dy,dz};
for(unsigned int i = 0 ; i < 3 ; ++i){
FReal*const targetsPotentials = inTargets->getPotentials(i);
FReal*const targetsForcesX = inTargets->getForcesX(i);
FReal*const targetsForcesY = inTargets->getForcesY(i);
FReal*const targetsForcesZ = inTargets->getForcesZ(i);
FReal*const sourcesPotentials = inNeighbors[idxNeighbors]->getPotentials(i);
FReal*const sourcesForcesX = inNeighbors[idxNeighbors]->getForcesX(i);
FReal*const sourcesForcesY = inNeighbors[idxNeighbors]->getForcesY(i);
FReal*const sourcesForcesZ = inNeighbors[idxNeighbors]->getForcesZ(i);
for(unsigned int j = 0 ; j < 3 ; ++j){
const FReal*const targetsPhysicalValues = inTargets->getPhysicalValues(j);
const FReal*const sourcesPhysicalValues = inNeighbors[idxNeighbors]->getPhysicalValues(j);
// potentials
FReal potentialCoef;
//if(i==j)
potentialCoef = inv_distance;
//else
// potentialCoef = FReal(0.);
// forces
FReal coef[3];
for(unsigned int k = 0 ; k < 3 ; ++k){
//if(i==j){
coef[k] = + r[k] * inv_distance_pow3 * (targetsPhysicalValues[idxTarget] * sourcesPhysicalValues[idxSource]);
//}
//else{
// coef[k] = FReal(0.);
//}
}// k
targetsForcesX[idxTarget] += coef[0];
targetsForcesY[idxTarget] += coef[1];
targetsForcesZ[idxTarget] += coef[2];
targetsPotentials[idxTarget] += ( potentialCoef * sourcesPhysicalValues[idxSource] );
sourcesForcesX[idxSource] -= coef[0];
sourcesForcesY[idxSource] -= coef[1];
sourcesForcesZ[idxSource] -= coef[2];
sourcesPotentials[idxSource] += potentialCoef * targetsPhysicalValues[idxTarget];
}// j
}// i
}
}
}
}
for(int idxTarget = 0 ; idxTarget < nbParticlesTargets ; ++idxTarget){
for(int idxSource = idxTarget + 1 ; idxSource < nbParticlesTargets ; ++idxSource){
FReal dx = targetsX[idxSource] - targetsX[idxTarget];
FReal dy = targetsY[idxSource] - targetsY[idxTarget];
FReal dz = targetsZ[idxSource] - targetsZ[idxTarget];
FReal inv_distance_pow2 = FReal(1.0) / (dx*dx + dy*dy + dz*dz);
FReal inv_distance = FMath::Sqrt(inv_distance_pow2);
FReal inv_distance_pow3 = inv_distance_pow2 * inv_distance;
FReal r[3]={dx,dy,dz};
for(unsigned int i = 0 ; i < 3 ; ++i){
FReal*const targetsPotentials = inTargets->getPotentials(i);
FReal*const targetsForcesX = inTargets->getForcesX(i);
FReal*const targetsForcesY = inTargets->getForcesY(i);
FReal*const targetsForcesZ = inTargets->getForcesZ(i);
for(unsigned int j = 0 ; j < 3 ; ++j){
const FReal*const targetsPhysicalValues = inTargets->getPhysicalValues(j);
// potentials
FReal potentialCoef;
//if(i==j)
potentialCoef = inv_distance;
//else
// potentialCoef = FReal(0.);
// forces
FReal coef[3];
for(unsigned int k = 0 ; k < 3 ; ++k){
//if(i==j){
coef[k] = + r[k] * inv_distance_pow3 * (targetsPhysicalValues[idxTarget] * targetsPhysicalValues[idxSource]);
//}
//else{
// coef[k] = FReal(0.);
//}
}// k
targetsForcesX[idxTarget] += coef[0];
targetsForcesY[idxTarget] += coef[1];
targetsForcesZ[idxTarget] += coef[2];
targetsPotentials[idxTarget] += ( potentialCoef * targetsPhysicalValues[idxSource] );
targetsForcesX[idxSource] -= coef[0];
targetsForcesY[idxSource] -= coef[1];
targetsForcesZ[idxSource] -= coef[2];
targetsPotentials[idxSource] += potentialCoef * targetsPhysicalValues[idxTarget];
}// j
}// i
}
}
}
/**
* @brief FullRemoteIOR
*/
template <class ContainerClass>
inline void FullRemoteIOR(ContainerClass* const FRestrict inTargets, ContainerClass* const inNeighbors[],
const int limiteNeighbors){
const int nbParticlesTargets = inTargets->getNbParticles();
const FReal*const targetsX = inTargets->getPositions()[0];
const FReal*const targetsY = inTargets->getPositions()[1];
const FReal*const targetsZ = inTargets->getPositions()[2];
for(int idxNeighbors = 0 ; idxNeighbors < limiteNeighbors ; ++idxNeighbors){
for(int idxTarget = 0 ; idxTarget < nbParticlesTargets ; ++idxTarget){
if( inNeighbors[idxNeighbors] ){
const int nbParticlesSources = inNeighbors[idxNeighbors]->getNbParticles();
const FReal*const sourcesX = inNeighbors[idxNeighbors]->getPositions()[0];
const FReal*const sourcesY = inNeighbors[idxNeighbors]->getPositions()[1];
const FReal*const sourcesZ = inNeighbors[idxNeighbors]->getPositions()[2];
for(int idxSource = 0 ; idxSource < nbParticlesSources ; ++idxSource){
// potential
FReal dx = sourcesX[idxSource] - targetsX[idxTarget];
FReal dy = sourcesY[idxSource] - targetsY[idxTarget];
FReal dz = sourcesZ[idxSource] - targetsZ[idxTarget];
FReal inv_distance_pow2 = FReal(1.0) / (dx*dx + dy*dy + dz*dz);
FReal inv_distance = FMath::Sqrt(inv_distance_pow2);
FReal inv_distance_pow3 = inv_distance_pow2 * inv_distance;
FReal r[3]={dx,dy,dz};
for(unsigned int i = 0 ; i < 3 ; ++i){
FReal*const targetsPotentials = inTargets->getPotentials(i);
FReal*const targetsForcesX = inTargets->getForcesX(i);
FReal*const targetsForcesY = inTargets->getForcesY(i);
FReal*const targetsForcesZ = inTargets->getForcesZ(i);
for(unsigned int j = 0 ; j < 3 ; ++j){
const FReal*const targetsPhysicalValues = inTargets->getPhysicalValues(j);
const FReal*const sourcesPhysicalValues = inNeighbors[idxNeighbors]->getPhysicalValues(j);
// potentials
FReal potentialCoef;
//if(i==j)
potentialCoef = inv_distance ;
//else
// potentialCoef = FReal(0.);
// forces
FReal coef[3];
for(unsigned int k = 0 ; k < 3 ; ++k){
//if(i==j){
coef[k] = + r[k] * inv_distance_pow3 * (targetsPhysicalValues[idxTarget] * sourcesPhysicalValues[idxSource]);
//}
//else{
// coef[k] = FReal(0.);
//}
}// k
targetsForcesX[idxTarget] += coef[0];
targetsForcesY[idxTarget] += coef[1];
targetsForcesZ[idxTarget] += coef[2];
targetsPotentials[idxTarget] += ( potentialCoef * sourcesPhysicalValues[idxSource] );
}// j
}// i
}
}
}
}
}
/**
* @brief MutualParticlesIOR
* @param sourceX
* @param sourceY
* @param sourceZ
* @param sourcePhysicalValue
* @param sourceForceX
* @param sourceForceY
* @param sourceForceZ
* @param sourcePotential
* @param targetX
* @param targetY
* @param targetZ
* @param targetPhysicalValue
* @param targetForceX
* @param targetForceY
* @param targetForceZ
* @param targetPotential
*/
inline void MutualParticlesIOR(const FReal sourceX,const FReal sourceY,const FReal sourceZ, const FReal* sourcePhysicalValue,
FReal* sourceForceX, FReal* sourceForceY, FReal* sourceForceZ, FReal* sourcePotential,
const FReal targetX,const FReal targetY,const FReal targetZ, const FReal* targetPhysicalValue,
FReal* targetForceX, FReal* targetForceY, FReal* targetForceZ, FReal* targetPotential
){
// GradGradR potential
FReal dx = sourceX - targetX;
FReal dy = sourceY - targetY;
FReal dz = sourceZ - targetZ;
FReal inv_distance_pow2 = FReal(1.0) / (dx*dx + dy*dy + dz*dz);
FReal inv_distance = FMath::Sqrt(inv_distance_pow2);
FReal inv_distance_pow3 = inv_distance_pow2 * inv_distance;
FReal r[3]={dx,dy,dz};
for(unsigned int i = 0 ; i < 3 ; ++i){
for(unsigned int j = 0 ; j < 3 ; ++j){
// potentials
FReal potentialCoef;
//if(i==j)
potentialCoef = inv_distance;
//else
// potentialCoef = FReal(0.);
// forces
FReal coef[3];
for(unsigned int k = 0 ; k < 3 ; ++k){
//if(i==j){
coef[k] = + r[k] * inv_distance_pow3 * (targetPhysicalValue[j] * sourcePhysicalValue[j]);
//}
//else{
// coef[k] = FReal(0.);
//}
}// k
targetForceX[i] += coef[0];
targetForceY[i] += coef[1];
targetForceZ[i] += coef[2];
targetPotential[i] += ( potentialCoef * sourcePhysicalValue[j] );
sourceForceX[i] -= coef[0];
sourceForceY[i] -= coef[1];
sourceForceZ[i] -= coef[2];
sourcePotential[i] += ( potentialCoef * targetPhysicalValue[j] );
}// j
}// i
}
}
#ifdef ScalFMM_USE_SSE
......
......@@ -52,7 +52,8 @@ class FUnifKernel
AbstractBaseClass;
/// Needed for M2L operator
FSmartPointer< M2LHandlerClass,FSmartPointerMemory> M2LHandler;
const M2LHandlerClass M2LHandler;
public:
/**
......@@ -64,9 +65,9 @@ public:
const FReal inBoxWidth,
const FPoint& inBoxCenter)
: FAbstractUnifKernel< CellClass, ContainerClass, MatrixKernelClass, ORDER, NVALS>(inTreeHeight,inBoxWidth,inBoxCenter),
M2LHandler(new M2LHandlerClass(AbstractBaseClass::MatrixKernel.getPtr(),
inTreeHeight,
inBoxWidth))// PB: for non homogeneous case
M2LHandler(AbstractBaseClass::MatrixKernel.getPtr(),
inTreeHeight,
inBoxWidth)
{ }
......@@ -79,7 +80,7 @@ public:
AbstractBaseClass::Interpolator->applyP2M(LeafCellCenter, AbstractBaseClass::BoxWidthLeaf,
LeafCell->getMultipole(idxRhs), SourceParticles);
// 2) apply Discrete Fourier Transform
M2LHandler->applyZeroPaddingAndDFT(LeafCell->getMultipole(idxRhs),
M2LHandler.applyZeroPaddingAndDFT(LeafCell->getMultipole(idxRhs),
LeafCell->getTransformedMultipole(idxRhs));
}
......@@ -100,7 +101,7 @@ public:
}
}
// 2) Apply Discete Fourier Transform
M2LHandler->applyZeroPaddingAndDFT(ParentCell->getMultipole(idxRhs),
M2LHandler.applyZeroPaddingAndDFT(ParentCell->getMultipole(idxRhs),
ParentCell->getTransformedMultipole(idxRhs));
}
}
......@@ -137,7 +138,7 @@ public:
for (int idx=0; idx<343; ++idx){
if (SourceCells[idx]){
M2LHandler->applyFC(idx, TreeLevel, scale,
M2LHandler.applyFC(idx, TreeLevel, scale,
SourceCells[idx]->getTransformedMultipole(idxRhs),
TransformedLocalExpansion);
}
......@@ -168,7 +169,7 @@ public:
{
for(int idxRhs = 0 ; idxRhs < NVALS ; ++idxRhs){
// 1) Apply Inverse Discete Fourier Transform
M2LHandler->unapplyZeroPaddingAndDFT(ParentCell->getTransformedLocal(idxRhs),
M2LHandler.unapplyZeroPaddingAndDFT(ParentCell->getTransformedLocal(idxRhs),
const_cast<CellClass*>(ParentCell)->getLocal(idxRhs));
// 2) apply Sx
for (unsigned int ChildIndex=0; ChildIndex < 8; ++ChildIndex){
......@@ -187,7 +188,7 @@ public:
for(int idxRhs = 0 ; idxRhs < NVALS ; ++idxRhs){
// 1) Apply Inverse Discete Fourier Transform
M2LHandler->unapplyZeroPaddingAndDFT(LeafCell->getTransformedLocal(idxRhs),
M2LHandler.unapplyZeroPaddingAndDFT(LeafCell->getTransformedLocal(idxRhs),
const_cast<CellClass*>(LeafCell)->getLocal(idxRhs));
// 2.a) apply Sx
......
......@@ -40,7 +40,7 @@ static void Compute(const MatrixKernelClass *const MatrixKernel, const FReal Cel
// allocate memory and store compressed M2L operators
if (FC) throw std::runtime_error("M2L operators are already set");
// PB: need to redefine some constant since not function from m2lhandler class
// dimensions of operators
const unsigned int order = ORDER;
const unsigned int nnodes = TensorTraits<ORDER>::nnodes;
const unsigned int ninteractions = 316;
......@@ -68,8 +68,8 @@ static void Compute(const MatrixKernelClass *const MatrixKernel, const FReal Cel
// init Discrete Fourier Transformator
const int dimfft = 1; // unidim FFT since fully circulant embedding