Commit 1045d47a authored by Quentin Khan's avatar Quentin Khan

Update the basic test kernel to used the new kernel data layout

 - Reuse the FGenericData class to implement the FTestCell.

 - Change FMM operators signature to take advantage of the new
   layout. The operators only take as parameters the data they may need
   instead of the whole cell. For instance (simplified):

   void M2M(CellClass* parent, CellClass** children);

   becomes

   void M2M(multipole_t*  parent_m,    symbolic_data_t* parent_s,
            multipole_t** children_ms, symbolic_data_t* children_ss);
parent 130602ac
......@@ -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 FTESTCELL_HPP
......@@ -19,100 +19,60 @@
#include <cstddef>
#include "FBasicCell.hpp"
/**
* @author Berenger Bramas (berenger.bramas@inria.fr)
* @class FBasicCell*
* @brief This class is used in the FTestKernels, please look at this class to know how to customize a cell.
*
* This cell simply store the data when up/down.
* It also shows how to be restored and saved, etc.
*/
class FTestCell : public FBasicCell, public FAbstractSendable {
protected:
// To store data during upward and downward pass
long long int dataUp, dataDown;
public:
FTestCell(): dataUp(0) , dataDown(0){
}
/** Default destructor */
virtual ~FTestCell(){
}
/** When doing the upward pass */
long long int getDataUp() const {
return this->dataUp;
}
/** When doing the upward pass */
void setDataUp(const long long int inData){
this->dataUp = inData;
}
/** When doing the downard pass */
long long int getDataDown() const {
return this->dataDown;
}
/** When doing the downard pass */
void setDataDown(const long long int inData){
this->dataDown = inData;
}
/** Make it like the begining */
void resetToInitialState(){
this->dataDown = 0;
this->dataUp = 0;
}
/////////////////////////////////////////////////
#include "Kernels/Generic/FGenericData.hpp"
/** Save the current cell in a buffer */
template <class BufferWriterClass>
void save(BufferWriterClass& buffer) const{
FBasicCell::save(buffer);
buffer << dataDown << dataUp;
}
/** Restore the current cell from a buffer */
template <class BufferReaderClass>
void restore(BufferReaderClass& buffer){
FBasicCell::restore(buffer);
buffer >> dataDown >> dataUp;
}
namespace scalfmm {
namespace detail {
namespace FTestCell_impl {
FSize getSavedSize() const {
return FSize(sizeof(long long int))*2 + FBasicCell::getSavedSize();
}
template<class Tag>
struct exp_impl {
using type = long long int;
/////////////////////////////////////////////////
type data;
type get() const {
return this->data;
}
void set(const type val) {
this->data = val;
}
void reset() {
this->data = 0;
}
template<class BufferWriter>
void save(BufferWriter& buffer) {
buffer << this->data;
}
template<class BufferReader>
void restore(BufferReader& buffer) {
buffer >> this->data;
}
FSize getSavedSize() const {
return sizeof(this->data);
}
template <class BufferWriterClass>
void serialize(BufferWriterClass& buffer) const {
buffer << this->data;
}
/** Deserialize only up data in a buffer */
template <class BufferReaderClass>
void deserialize(BufferReaderClass& buffer){
buffer >> this->data;
}
};
/** Serialize only up data in a buffer */
template <class BufferWriterClass>
void serializeUp(BufferWriterClass& buffer) const {
buffer << this->dataUp;
}
/** Deserialize only up data in a buffer */
template <class BufferReaderClass>
void deserializeUp(BufferReaderClass& buffer){
buffer >> this->dataUp;
}
using multipole_t = scalfmm::detail::FTestCell_impl::exp_impl<class MultipoleTag>;
using local_exp_t = scalfmm::detail::FTestCell_impl::exp_impl<class LocalExpansionTag>;
/** Serialize only down data in a buffer */
template <class BufferWriterClass>
void serializeDown(BufferWriterClass& buffer) const {
buffer << this->dataDown;
}
/** Deserialize only up data in a buffer */
template <class BufferReaderClass>
void deserializeDown(BufferReaderClass& buffer){
buffer >> this->dataDown;
}
}
}
}
FSize getSavedSizeDown() const {
return FSize(sizeof(long long int));
}
FSize getSavedSizeUp() const {
return FSize(sizeof(long long int));
}
};
using FTestCell = FGenericData<
scalfmm::detail::FTestCell_impl::multipole_t,
scalfmm::detail::FTestCell_impl::local_exp_t
>;
#endif //FTESTCELL_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 FTESTKERNELS_HPP
......@@ -47,47 +47,72 @@ public:
}
/** Before upward */
void P2M(CellClass* const pole, const ContainerClass* const particles) override {
template<class Symb>
void P2M(typename CellClass::multipole_t* const leaf_multipole,
const Symb* const /* leaf_symbolic_data */,
const ContainerClass* const particles)
{
// the pole represents all particles under
pole->setDataUp(pole->getDataUp() + particles->getNbParticles());
leaf_multipole->set(leaf_multipole->get() + particles->getNbParticles());
}
/** During upward */
void M2M(CellClass* const FRestrict pole, const CellClass *const FRestrict *const FRestrict child, const int /*level*/) override {
template<class Symb>
void M2M(typename CellClass::multipole_t * const node_multipole,
const Symb* const /*node_symbolic_data*/ ,
const typename CellClass::multipole_t * const * const child_multipoles,
const Symb* const /* child_symbolic_data */ [])
{
// 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());
if(child_multipoles[idx]){
node_multipole->set(node_multipole->get() + child_multipoles[idx]->get());
}
}
}
/** Before Downward */
void M2L(CellClass* const FRestrict pole, const CellClass* distantNeighbors[], const int /*position*/[],
const int size, const int /*level*/) override {
template<class Symb>
void M2L(typename CellClass::local_expansion_t* const node_local_expansion,
const Symb* const /*node_symbolic_data*/,
const typename CellClass::multipole_t* const v_item_multipoles[],
const Symb* const /*v_item_symbolic_data*/[],
const int /*position*/[],
const int v_item_data_size)
{
// The pole is impacted by what represent other poles
for(int idx = 0 ; idx < size ; ++idx){
pole->setDataDown(pole->getDataDown() + distantNeighbors[idx]->getDataUp());
for(int idx = 0 ; idx < v_item_data_size ; ++idx){
node_local_expansion->set(node_local_expansion->get()
+ v_item_multipoles[idx]->get());
}
}
/** During Downward */
void L2L(const CellClass*const FRestrict local, CellClass* FRestrict *const FRestrict child, const int /*level*/) override {
template<class Symb>
void L2L(const typename CellClass::local_expansion_t* const node_local_exp,
const Symb* const /*node_symbolic_data*/,
typename CellClass::local_expansion_t** const child_local_exps,
const Symb* const /*child_symbolic_data*/[])
{
// 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());
if(child_local_exps[idx]){
child_local_exps[idx]->set(node_local_exp->get()
+ child_local_exps[idx]->get());
}
}
}
/** After Downward */
void L2P(const CellClass* const local, ContainerClass*const particles) override {
// The particles is impacted by the parent cell
template<class Symb>
void L2P(const typename CellClass::local_expansion_t* const leaf_local_exp,
const Symb* const /* target_symbolic_data */,
ContainerClass* const particles)
{
// The particles is impacted by the parent cell
long long int*const particlesAttributes = particles->getDataDown();
for(FSize idxPart = 0 ; idxPart < particles->getNbParticles() ; ++idxPart){
particlesAttributes[idxPart] += local->getDataDown();
particlesAttributes[idxPart] += leaf_local_exp->get();
}
}
......@@ -155,8 +180,8 @@ void ValidateFMMAlgo(OctreeClass* const tree){
long long int NbPart = 0;
{ // Check that each particle has been summed with all other
tree->forEachCellLeaf([&](CellClass* cell, LeafClass* leaf){
if(cell->getDataUp() != leaf->getSrc()->getNbParticles() ){
std::cout << "Problem P2M : " << cell->getDataUp() <<
if(cell->getMultipoleData().get() != leaf->getSrc()->getNbParticles() ){
std::cout << "Problem P2M : " << cell->getMultipoleData().get() <<
" (should be " << leaf->getSrc()->getNbParticles() << ")\n";
}
NbPart += leaf->getSrc()->getNbParticles();
......@@ -167,7 +192,7 @@ void ValidateFMMAlgo(OctreeClass* const tree){
octreeIterator.moveDown();
long long int res = 0;
do{
res += octreeIterator.getCurrentCell()->getDataUp();
res += octreeIterator.getCurrentCell()->getMultipoleData().get();
} while(octreeIterator.moveRight());
if(res != NbPart){
std::cout << "Problem M2M at level 1 : " << res << "\n";
......@@ -179,7 +204,7 @@ void ValidateFMMAlgo(OctreeClass* const tree){
for(int idxLevel = TreeHeight - 1 ; idxLevel > 1 ; --idxLevel ){
long long int res = 0;
do{
res += octreeIterator.getCurrentCell()->getDataUp();
res += octreeIterator.getCurrentCell()->getMultipoleData().get();
} while(octreeIterator.moveRight());
if(res != NbPart){
std::cout << "Problem M2M at level " << idxLevel << " : " << res << "\n";
......@@ -211,5 +236,3 @@ void ValidateFMMAlgo(OctreeClass* const tree){
#endif //FTESTKERNELS_HPP
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment