diff --git a/Src/Kernels/Rotation/FRotationCell.hpp b/Src/Kernels/Rotation/FRotationCell.hpp index 593f96535964fed23c3476b51d939a7eb0bc001b..7585e1c896a69e54112a5b7c3a6d493b23cd3b84 100644 --- a/Src/Kernels/Rotation/FRotationCell.hpp +++ b/Src/Kernels/Rotation/FRotationCell.hpp @@ -4,13 +4,13 @@ // This software is a computer program whose purpose is to compute the FMM. // // This software is governed by the CeCILL-C and LGPL licenses and -// abiding by the rules of distribution of free software. -// +// abiding by the rules of distribution of free software. +// // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public and CeCILL-C Licenses for more details. -// "http://www.cecill.info". +// "http://www.cecill.info". // "http://www.gnu.org/licenses". // =================================================================================== #ifndef FROTATIONCELL_HPP @@ -37,75 +37,68 @@ template <class FReal, int P> class FRotationCell : public FBasicCell, public FAbstractSendable { protected: - //< Size of multipole vector - static const int MultipoleSize = ((P+2)*(P+1))/2; // Artimethique suite (n+1)*n/2 - //< Size of local vector - static const int LocalSize = ((P+2)*(P+1))/2; // Artimethique suite (n+1)*n/2 - //< Multipole vector (static memory) - FComplex<FReal> multipole_exp[MultipoleSize]; //< For multipole extenssion - //< Local vector (static memory) - FComplex<FReal> local_exp[LocalSize]; //< For local extenssion + template<std::size_t S, class Tag> + struct expansion_impl { + enum {Size = S}; + FComplex<FReal> exp[Size]; + + FComplex<FReal>* get() noexcept { + return exp; + } + const FComplex<FReal>* get() const noexcept { + return exp; + } + + int getSize() const noexcept { + return Size; + } + + void reset() noexcept { + for(int idx = 0; idx < Size; ++idx) { + exp[idx].setRealImag(FReal(0.0), FReal(0.0)); + } + } + + template<class BufferWriterClass> + void serialize(BufferWriterClass& buffer) const { + buffer.write(exp, Size); + } + template<class BufferReaderClass> + void deserialize(BufferReaderClass& buffer) { + buffer.fillArray(exp, Size); + } + }; public: - /** Default constructor - * Put 0 in vectors - */ - FRotationCell(){ - } - /** Copy constructor - * Copy the value in the vectors - */ - FRotationCell(const FRotationCell& other){ - (*this) = other; - } + using multipole_t = expansion_impl<((P+2)*(P+1))/2, class multipole_tag>; + using local_expansion_t = expansion_impl<((P+2)*(P+1))/2, class local_expansion_tag>; - /** Default destructor */ - virtual ~FRotationCell(){ - } +protected: - /** Copy operator - * copies only the value in the vectors - */ - FRotationCell& operator=(const FRotationCell& other) { - FMemUtils::copyall(multipole_exp, other.multipole_exp, MultipoleSize); - FMemUtils::copyall(local_exp, other.local_exp, LocalSize); - return *this; - } + multipole_t m_data; + local_expansion_t l_data; - /** Get Multipole array */ - const FComplex<FReal>* getMultipole() const { - return multipole_exp; - } - /** Get Local array */ - const FComplex<FReal>* getLocal() const { - return local_exp; - } +public: - /** Get Multipole array */ - FComplex<FReal>* getMultipole() { - return multipole_exp; + const multipole_t& getMultipoleData() const noexcept { + return m_data; } - /** Get Local array */ - FComplex<FReal>* getLocal() { - return local_exp; + multipole_t& getMultipoleData() { + return m_data; } - - int getArraySize() const - { - return MultipoleSize; + const local_expansion_t& getLocalExpansionData() const noexcept { + return l_data; + } + local_expansion_t& getLocalExpansionData() { + return l_data; } - /** Make it like the begining */ void resetToInitialState(){ - for(int idx = 0 ; idx < MultipoleSize ; ++idx){ - multipole_exp[idx].setRealImag(FReal(0.0), FReal(0.0)); - } - for(int idx = 0 ; idx < LocalSize ; ++idx){ - local_exp[idx].setRealImag(FReal(0.0), FReal(0.0)); - } + m_data.reset(); + l_data.reset(); } /////////////////////////////////////////////////////// @@ -113,28 +106,28 @@ public: /////////////////////////////////////////////////////// template <class BufferWriterClass> void serializeUp(BufferWriterClass& buffer) const{ - buffer.write(multipole_exp, MultipoleSize); + m_data.serialize(buffer); } template <class BufferReaderClass> void deserializeUp(BufferReaderClass& buffer){ - buffer.fillArray(multipole_exp, MultipoleSize); + m_data.deserialize(buffer); } template <class BufferWriterClass> void serializeDown(BufferWriterClass& buffer) const{ - buffer.write(local_exp, LocalSize); + l_data.serialize(buffer); } template <class BufferReaderClass> void deserializeDown(BufferReaderClass& buffer){ - buffer.fillArray(local_exp, LocalSize); + l_data.deserialize(buffer); } FSize getSavedSizeUp() const { - return ((FSize) sizeof(FComplex<FReal>)) * (MultipoleSize); + return ((FSize) sizeof(FComplex<FReal>)) * (multipole_t::Size); } FSize getSavedSizeDown() const { - return ((FSize) sizeof(FComplex<FReal>)) * (LocalSize); + return ((FSize) sizeof(FComplex<FReal>)) * (local_expansion_t::Size); } /////////////////////////////////////////////////////// @@ -143,18 +136,18 @@ public: template <class BufferWriterClass> void save(BufferWriterClass& buffer) const{ FBasicCell::save(buffer); - buffer.write(multipole_exp, MultipoleSize); - buffer.write(local_exp, LocalSize); + m_data.serialize(); + l_data.serialize(); } template <class BufferReaderClass> void restore(BufferReaderClass& buffer){ FBasicCell::restore(buffer); - buffer.fillArray(multipole_exp, MultipoleSize); - buffer.fillArray(local_exp, LocalSize); + m_data.deserialize(); + l_data.deserialize(); } FSize getSavedSize() const { - return FSize(((int) sizeof(FComplex<FReal>)) * (MultipoleSize + LocalSize) + return FSize(((int) sizeof(FComplex<FReal>)) * (multipole_t::Size + local_expansion_t::Size) + FBasicCell::getSavedSize()); } }; diff --git a/Src/Kernels/Rotation/FRotationKernel.hpp b/Src/Kernels/Rotation/FRotationKernel.hpp index 513a7ab6b78f6fdf968282b841700937f8c4d9cb..7b0163706a86d86abc34c6c2acbde79ba16f8bd2 100644 --- a/Src/Kernels/Rotation/FRotationKernel.hpp +++ b/Src/Kernels/Rotation/FRotationKernel.hpp @@ -909,13 +909,17 @@ public: * \omega (q,a) = q \frac{a^{l}}{(l+|m|)!} P_{lm}(cos( \alpha ) )e^{-im \beta} * \f] */ - void P2M(CellClass* const inPole, const ContainerClass* const inParticles ) override { + template<class SymbolicData> + void P2M(typename CellClass::multipole_t* const LeafMultipole, + const SymbolicData* const LeafSymb, + const ContainerClass* const inParticles ) + { const FReal i_pow_m[4] = {0, FMath::FPiDiv2<FReal>(), FMath::FPi<FReal>(), -FMath::FPiDiv2<FReal>()}; // w is the multipole moment - FComplex<FReal>* FRestrict const w = inPole->getMultipole(); + FComplex<FReal>* FRestrict const w = LeafMultipole->get(); // Copying the position is faster than using cell position - const FPoint<FReal> cellPosition = getLeafCenter(inPole->getCoordinate()); + const FPoint<FReal> cellPosition = getLeafCenter(LeafSymb->getCoordinate()); // We need a legendre array FReal legendre[SizeArray]; @@ -972,17 +976,23 @@ public: * then transfer using the formula * and finaly rotate back. */ - void M2M(CellClass* const FRestrict inPole, const CellClass*const FRestrict *const FRestrict inChildren, const int inLevel) override { + template<class SymbolicData> + void M2M(typename CellClass::multipole_t* const FRestrict ParentMultipole, + const SymbolicData* const ParentSymb, + const typename CellClass::multipole_t*const FRestrict *const FRestrict ChildMultipoles, + const SymbolicData* const /*ChildSymbs*/[]) + { + int level = static_cast<int>(ParentSymb->getLevel()); // Get the translation coef for this level (same for all child) - const FReal*const coef = M2MTranslationCoef[inLevel]; + const FReal*const coef = M2MTranslationCoef[level]; // A buffer to copy the source w allocated once FComplex<FReal> source_w[SizeArray]; // For all children for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ // if child exists - if(inChildren[idxChild]){ + if(ChildMultipoles[idxChild]){ // Copy the source - FMemUtils::copyall(source_w, inChildren[idxChild]->getMultipole(), SizeArray); + FMemUtils::copyall(source_w, ChildMultipoles[idxChild]->get(), SizeArray); // rotate it forward RotationZVectorsMul(source_w,rotationExpMinusImPhi[idxChild]); @@ -1012,7 +1022,7 @@ public: RotationZVectorsMul(target_w,rotationExpImPhi[idxChild]); // Sum the result - FMemUtils::addall( inPole->getMultipole(), target_w, SizeArray); + FMemUtils::addall( ParentMultipole->get(), target_w, SizeArray); } } } @@ -1028,16 +1038,20 @@ public: * then transfer using the formula * and finaly rotate back. */ - void M2L(CellClass* const FRestrict inLocal, const CellClass* inInteractions[], const int /*inSize*/, const int inLevel) { + void M2L(typename CellClass::local_expansion_t* const FRestrict NodeLocalExpansion, + const typename CellClass::multipole_t* const FRestrict NeighborMultipoles[], + const int /*inSize*/, + const int inLevel) + { // To copy the multipole data allocated once FComplex<FReal> source_w[SizeArray]; // For all children for(int idxNeigh = 0 ; idxNeigh < 343 ; ++idxNeigh){ // if interaction exits - if(inInteractions[idxNeigh]){ + if(NeighborMultipoles[idxNeigh]){ const FReal*const coef = M2LTranslationCoef[inLevel][idxNeigh]; // Copy multipole data into buffer - FMemUtils::copyall(source_w, inInteractions[idxNeigh]->getMultipole(), SizeArray); + FMemUtils::copyall(source_w, NeighborMultipoles[idxNeigh]->get(), SizeArray); // Rotate RotationZVectorsMul(source_w,rotationM2LExpMinusImPhi[idxNeigh]); @@ -1070,22 +1084,29 @@ public: RotationZVectorsMul(target_u,rotationM2LExpMinusImPhi[idxNeigh]); // Sum - FMemUtils::addall(inLocal->getLocal(), target_u, SizeArray); + FMemUtils::addall(NodeLocalExpansion->get(), target_u, SizeArray); } } } - void M2L(CellClass* const FRestrict inLocal, const CellClass* inInteractions[], - const int neighborPositions[], const int inSize, const int inLevel) override { + template<class SymbolicData> + void M2L(typename CellClass::local_expansion_t * const FRestrict TargetExpansion, + const SymbolicData* const TargetSymb, + const typename CellClass::multipole_t * const FRestrict SourceMultipoles[], + const SymbolicData* const FRestrict /*SourceSymbs*/[], + const int neighborPositions[], + const int inSize) + { + int level = static_cast<int>(TargetSymb->getLevel()); // To copy the multipole data allocated once FComplex<FReal> source_w[SizeArray]; // For all children for(int idxExistingNeigh = 0 ; idxExistingNeigh < inSize ; ++idxExistingNeigh){ const int idxNeigh = neighborPositions[idxExistingNeigh]; // if interaction exits - const FReal*const coef = M2LTranslationCoef[inLevel][idxNeigh]; + const FReal*const coef = M2LTranslationCoef[level][idxNeigh]; // Copy multipole data into buffer - FMemUtils::copyall(source_w, inInteractions[idxExistingNeigh]->getMultipole(), SizeArray); + FMemUtils::copyall(source_w, SourceMultipoles[idxExistingNeigh]->get(), SizeArray); // Rotate RotationZVectorsMul(source_w,rotationM2LExpMinusImPhi[idxNeigh]); @@ -1118,7 +1139,7 @@ public: RotationZVectorsMul(target_u,rotationM2LExpMinusImPhi[idxNeigh]); // Sum - FMemUtils::addall(inLocal->getLocal(), target_u, SizeArray); + FMemUtils::addall(TargetExpansion->get(), target_u, SizeArray); } } @@ -1133,17 +1154,23 @@ public: * then transfer using the formula * and finaly rotate back. */ - void L2L(const CellClass* const FRestrict inLocal, CellClass* FRestrict *const FRestrict inChildren, const int inLevel) override { + template<class SymbolicData> + void L2L(const typename CellClass::local_expansion_t * const FRestrict ParentLocalExpansion, + const SymbolicData* const ParentSymb, + typename CellClass::local_expansion_t * FRestrict * const FRestrict ChildLocalExpansion, + const SymbolicData* const /*ChildSymbs*/[]) + { + int level = static_cast<int>(ParentSymb->getLevel()); // Get the translation coef for this level (same for all chidl) - const FReal*const coef = L2LTranslationCoef[inLevel]; + const FReal*const coef = L2LTranslationCoef[level]; // To copy the source local allocated once FComplex<FReal> source_u[SizeArray]; // For all children for(int idxChild = 0 ; idxChild < 8 ; ++idxChild){ // if child exists - if(inChildren[idxChild]){ + if(ChildLocalExpansion[idxChild]){ // Copy the local data into the buffer - FMemUtils::copyall(source_u, inLocal->getLocal(), SizeArray); + FMemUtils::copyall(source_u, ParentLocalExpansion->get(), SizeArray); // Rotate RotationZVectorsMul(source_u,rotationExpImPhi[idxChild]); @@ -1172,7 +1199,7 @@ public: RotationZVectorsMul(target_u,rotationExpMinusImPhi[idxChild]); // Sum in child - FMemUtils::addall(inChildren[idxChild]->getLocal(), target_u, SizeArray); + FMemUtils::addall(ChildLocalExpansion[idxChild]->get(), target_u, SizeArray); } } } @@ -1195,13 +1222,17 @@ public: * F_{ \phi } = -\frac{1}{r sin \phi} \sum_{j=0}^P \sum_{k=1}^j{(-2k) Im(u_{j,k} I_{j,k}(r, \theta, \phi)) } * \f] */ - void L2P(const CellClass* const inLocal, ContainerClass* const inParticles) override { + template<class SymbolicData> + void L2P(const typename CellClass::local_expansion_t* const LeafLocalExpansion, + const SymbolicData* const LeafSymb, + ContainerClass* const inParticles) + { const FReal i_pow_m[4] = {0, FMath::FPiDiv2<FReal>(), FMath::FPi<FReal>(), -FMath::FPiDiv2<FReal>()}; // Take the local value from the cell - const FComplex<FReal>* FRestrict const u = inLocal->getLocal(); + const FComplex<FReal>* FRestrict const u = LeafLocalExpansion->get(); // Copying the position is faster than using cell position - const FPoint<FReal> cellPosition = getLeafCenter(inLocal->getCoordinate()); + const FPoint<FReal> cellPosition = getLeafCenter(LeafSymb->getCoordinate()); // For all particles in the leaf box const FReal*const physicalValues = inParticles->getPhysicalValues();