Commit 66ca7e5a authored by PIACIBELLO Cyrille's avatar PIACIBELLO Cyrille

Changes to forward the Leaf Cell distinction in ScalFMM inside the API

parent 5f801fe8
......@@ -173,6 +173,28 @@ typedef void (*Callback_copy_cell)(void * userDatas, FSize size, void * memoryAl
typedef void (*Callback_finalize_leaf)(int level, FSize nbParts, const FSize * idxParts, long long morton_index, double center[3],
void * cellDatas, void * userDatas);
/**
* @brief Callback to initialise data inside the Leaves
* @param level current level of leaves (ie height of the tree)
* @param nbParts Number of particles inside that leaf"
* @param idxParts array of size nbParts, containing the indices of each parts
* @param morton_index of the current cell
* @param center of the current leaf (3 double)
* @param userData cell user data
* @param userData Kernel user data
*/
typedef void* (*Callback_init_leaf)(int level, FSize nbParts, const FSize * idxParts, long long morton_index, double center[3],
void * cellDatas, void * userDatas);
/**
* @brief Callback to free data inside the Leaves
* @param nbParts Number of particles inside that leaf
* @param idxParts array of size nbParts, containing the indices of each parts
* @param cellDatas ptr to the cell.
* @param leafData leaf to destroy
* @param ptr to userData.
*/
typedef void (*Callback_free_leaf)(void * cellDatas, FSize nbParts, const FSize * idxParts, void * leafData, void * userDatas);
/**
......@@ -192,6 +214,8 @@ typedef struct User_Scalfmm_Cell_Descriptor{
Callback_get_cell_size user_get_size;
Callback_copy_cell user_copy_cell;
Callback_restore_cell user_restore_cell;
Callback_init_leaf user_init_leaf;
Callback_free_leaf user_free_leaf;
}Scalfmm_Cell_Descriptor;
......@@ -447,11 +471,12 @@ void scalfmm_algorithm_config(scalfmm_handle Handle,scalfmm_algorithm config);
/**
* @brief Function to be filled by user's P2M
* @param nbParticles number of particle in current leaf
* @param leafCell current leaf
* @param cellData current cell
* @param leafData currentLeaf
* @param particleIndexes indexes of particles currently computed
* @param userData datas specific to the user's kernel
*/
typedef void (*Callback_P2M)(void* leafCell, FSize nbParticles, const FSize* particleIndexes, void* userData);
typedef void (*Callback_P2M)(void* cellData, void * leafData, FSize nbParticles, const FSize* particleIndexes, void* userData);
/**
* @brief Function to be filled by user's M2M
......@@ -506,54 +531,63 @@ typedef void (*Callback_L2L)(int level, void* parentCell, int childPosition, voi
/**
* @brief Function to be filled by user's L2P
* @param leafCell leaf to be filled
* @param cellData cell to be read
* @param leafData leaf to be written
* @param nbParticles number of particles in the current leaf
* @param particleIndexes indexes of particles currently computed
* @param userData datas specific to the user's kernel
*/
typedef void (*Callback_L2P)(void* leafCell, FSize nbParticles,const FSize* particleIndexes, void* userData);
typedef void (*Callback_L2P)(void* cellData, void * leafData, FSize nbParticles,const FSize* particleIndexes, void* userData);
/**
* @brief Function to be filled by user's P2P
* @param targetLeaf ptr to user target leaf
* @param nbParticles number of particle in current leaf
* @param particleIndexes indexes of particles currently computed
* @param sourceLeaf ptr to user source leaf
* @param nbSourceParticles number of particles in source leaf
* @param sourceParticleIndexes indexes of cource particles currently computed
* @param userData datas specific to the user's kernel
*/
typedef void (*Callback_P2P)(FSize nbParticles, const FSize* particleIndexes, FSize nbSourceParticles, const FSize* sourceParticleIndexes, void* userData);
typedef void (*Callback_P2P)(void * targetLeaf, FSize nbParticles, const FSize* particleIndexes,
void * sourceLeaf, FSize nbSourceParticles, const FSize* sourceParticleIndexes, void* userData);
/**
* @brief Function to be filled by user's P2P
* @attention This function is symmetrc, thus when a call is done
* @attention This function is symmetric, thus when a call is done
* between target and neighbors cell, the user needs to apply the target
* field onto the neighbors cells too.
* @param targetLeaf ptr to user target leaf
* @param nbParticles number of particle in current leaf
* @param particleIndexes indexes of particles currently computed
* @param sourceCell array of the neighbors source cells
* @param sourceLeaves array of ptr to user source leaves.
* @param sourceParticleIndexes array of indices of source particles currently computed
* @param sourceNbPart array containing the number of part in each neighbors
* @param sourcePosition array containing relative position of the neighbor
* @param size : size of the arrays (thus, number of existing neighbor cell)
* @param userData datas specific to the user's kernel
*/
typedef void (*Callback_P2PFull)(FSize nbParticles, const FSize* particleIndexes,
typedef void (*Callback_P2PFull)(void * targetLeaf, FSize nbParticles, const FSize* particleIndexes,
void ** sourceLeaves,
const FSize ** sourceParticleIndexes,FSize * sourceNbPart,
const int * sourcePosition, const int size, void* userData);
/**
* @brief Function to be filled by user's P2P inside the leaf
* @param targetLeaf ptr to user target leaf
* @param nbParticles number of particle in current leaf
* @param particleIndexes indexes of particles currently computed
* @param userData datas specific to the user's kernel
*/
typedef void (*Callback_P2PInner)(FSize nbParticles, const FSize* particleIndexes, void* userData);
typedef void (*Callback_P2PInner)(void * targetLeaf,FSize nbParticles, const FSize* particleIndexes, void* userData);
/**
* @brief Function to be filled by user's P2P
* @param targetLeaf ptr to user target leaf
* @param nbParticles number of particle in current leaf
* @param particleIndexes indexes of particles currently computed
* @praram sourceLeaf ptr to user source leaf
* @param nbSourceParticles number of particles in source leaf
* @param sourceParticleIndexes indexes of cource particles currently computed
* @param userData datas specific to the user's kernel
......@@ -562,7 +596,8 @@ typedef void (*Callback_P2PInner)(FSize nbParticles, const FSize* particleIndexe
* thus if a call is done with cell1 as source and cell2 as target, no
* call will be done with cell2 as source and cell1 as target.
*/
typedef void (*Callback_P2PSym)(FSize nbParticles, const FSize* particleIndexes, FSize nbSourceParticles, const FSize* sourceParticleIndexes, void* userData);
typedef void (*Callback_P2PSym)(void * targetLeaf, FSize nbParticles, const FSize* particleIndexes,
void * sourceLeaf, FSize nbSourceParticles, const FSize* sourceParticleIndexes, void* userData);
/**
* @brief Function to be filled by user's method to reset a user's cell
......
......@@ -17,10 +17,10 @@ extern "C" scalfmm_handle scalfmm_init(/*int TreeHeight,double BoxWidth,
switch(KernelType){
case 0:
typedef FP2PParticleContainerIndexed<FReal> ContainerClass;
typedef FTypedLeaf<FReal,ContainerClass> LeafClass;
typedef FUserLeafContainer<FReal> UserContainerClass;
typedef FTypedLeaf<FReal,UserContainerClass> UserLeafClass;
handle->engine = new FUserKernelEngine<FReal,LeafClass>(/*TreeHeight, BoxWidth, BoxCenter, */KernelType,algo);
handle->engine = new FUserKernelEngine<FReal,UserLeafClass>(/*TreeHeight, BoxWidth, BoxCenter, */KernelType,algo);
break;
case 1:
......@@ -59,10 +59,10 @@ extern "C" scalfmm_handle scalfmm_init(/*int TreeHeight,double BoxWidth,
//No Source/Targets distinction
switch(KernelType){
case 0:
typedef FP2PParticleContainerIndexed<FReal> ContainerClass;
typedef FSimpleLeaf<FReal,ContainerClass> LeafClass;
typedef FUserLeafContainer<FReal> UserContainerClass;
typedef FSimpleLeaf<FReal,UserContainerClass> UserLeafClass;
handle->engine = new FUserKernelEngine<FReal,LeafClass>(/*TreeHeight, BoxWidth, BoxCenter, */KernelType,algo);
handle->engine = new FUserKernelEngine<FReal,UserLeafClass>(/*TreeHeight, BoxWidth, BoxCenter, */KernelType,algo);
break;
case 1:
......@@ -121,8 +121,8 @@ extern "C" scalfmm_handle scalfmm_init_distributed( scalfmm_kernel_type KernelTy
//Only the User Defined Kernel version (UDK) is available.
typedef double FReal;
typedef FP2PParticleContainerIndexed<FReal> ContainerClass;
typedef FSimpleLeaf<FReal,ContainerClass> LeafClass;
typedef FUserLeafContainer<FReal> ContainerClass;
typedef FSimpleLeaf<FReal,ContainerClass> LeafClass;
handle->engine = (new FUserKernelDistrEngine<FReal,LeafClass>(KernelType,algo,comm));
return handle;
......
......@@ -128,7 +128,7 @@ private:
using Parent = FUserKernelEngine<FReal,LeafClass>;
//Same as in Parent class.
using ContainerClass = FP2PParticleContainerIndexed<FReal>;
using ContainerClass = FUserLeafContainer<FReal>;
using OctreeClass = FOctree<FReal,CoreCellDist,ContainerClass,LeafClass>;
using CoreKernelClass = CoreKernel<CoreCellDist,ContainerClass>;
......
......@@ -22,6 +22,7 @@
#define FUSERKERNELENGINE_HPP
#include "FScalFMMEngine.hpp"
#include "FUserLeafContainer.hpp"
#include <vector>
/**
......@@ -48,6 +49,15 @@ public:
return user_cell_descriptor.user_free_cell;
}
static Callback_init_leaf GetInitLeaf(){
return user_cell_descriptor.user_init_leaf;
}
static Callback_free_leaf GetFreeLeaf(){
return user_cell_descriptor.user_free_leaf;
}
CoreCell() : userData(nullptr) {
}
......@@ -108,7 +118,7 @@ public:
/** Do nothing */
virtual void P2M(CellClass* const cell, const ContainerClass* const container) {
if(kernel.p2m) kernel.p2m(cell->getContainer(), container->getNbParticles(), container->getIndexes().data(), userData);
if(kernel.p2m) kernel.p2m(cell->getContainer(), container->getContainer(), container->getNbParticles(), container->getIndexes().data(), userData);
}
/** Do nothing */
......@@ -158,7 +168,7 @@ public:
virtual void L2P(const CellClass* const cell, ContainerClass* const container){
// std::cout << "L2P with "<< container->getNbParticles() <<" - over "<< cell<< " and "<<cell->getContainer() <<" Indexes : ["<<container->getIndexes()[0] <<"]\n";
if(kernel.l2p) kernel.l2p(cell->getContainer(), container->getNbParticles(), container->getIndexes().data(), userData);
if(kernel.l2p) kernel.l2p(cell->getContainer(),container->getContainer(), container->getNbParticles(), container->getIndexes().data(), userData);
}
virtual void P2POuter(const FTreeCoordinate& inLeafPosition,
......@@ -175,33 +185,32 @@ public:
virtual void P2P(const FTreeCoordinate& inLeafPosition,
ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict sources,
ContainerClass* const neighbors[],const int sourcePosition[], const int size){
if(kernel.p2pinner) kernel.p2pinner(targets->getNbParticles(), targets->getIndexes().data(), userData);
if(kernel.p2pinner) kernel.p2pinner(targets->getContainer(),targets->getNbParticles(), targets->getIndexes().data(), userData);
if(kernel.p2p_full){
//Create the arrays of size and indexes
if(size != 0){
FSize * nbPartPerNeighbors = new FSize[size];
const FSize ** indicesPerNeighbors = new const FSize*[size];
for(int idx=0 ; idx<size ; ++idx){
nbPartPerNeighbors[idx] = neighbors[idx]->getNbParticles();
indicesPerNeighbors[idx] = neighbors[idx]->getIndexes().data();
}
kernel.p2p_full(targets->getNbParticles(),targets->getIndexes().data(),indicesPerNeighbors,nbPartPerNeighbors,sourcePosition,size,userData);
}else{
kernel.p2p_full(targets->getNbParticles(),targets->getIndexes().data(),nullptr,nullptr,sourcePosition,0,userData);
FSize * nbPartPerNeighbors = new FSize[size];
const FSize ** indicesPerNeighbors = new const FSize*[size];
//create artificial array of void * :
void ** arrayOfUserContainer = new void *[size];
for(int idx=0 ; idx<size ; ++idx){
nbPartPerNeighbors[idx] = neighbors[idx]->getNbParticles();
indicesPerNeighbors[idx] = neighbors[idx]->getIndexes().data();
arrayOfUserContainer[idx] = neighbors[idx]->getContainer();
}
kernel.p2p_full(targets->getContainer(),targets->getNbParticles(),targets->getIndexes().data(),arrayOfUserContainer,indicesPerNeighbors,nbPartPerNeighbors,sourcePosition,size,userData);
}
if(kernel.p2p_sym){
for(int idx = 0 ; ((idx < size) && (sourcePosition[idx] < 14)) ; ++idx){
kernel.p2p_sym(targets->getNbParticles(), targets->getIndexes().data(),
neighbors[idx]->getNbParticles(), neighbors[idx]->getIndexes().data(), userData);
kernel.p2p_sym(targets->getContainer(),targets->getNbParticles(), targets->getIndexes().data(),
neighbors[idx]->getContainer(),neighbors[idx]->getNbParticles(), neighbors[idx]->getIndexes().data(), userData);
}
}
else{
if(kernel.p2p){
for(int idx = 0 ; idx < size ; ++idx){
kernel.p2p(targets->getNbParticles(), targets->getIndexes().data(),
neighbors[idx]->getNbParticles(), neighbors[idx]->getIndexes().data(), userData);
kernel.p2p(targets->getContainer(),targets->getNbParticles(), targets->getIndexes().data(),
neighbors[idx]->getContainer(),neighbors[idx]->getNbParticles(), neighbors[idx]->getIndexes().data(), userData);
}
}
}
......@@ -236,7 +245,7 @@ class FUserKernelEngine : public FScalFMMEngine<FReal>{
private:
//Typedefs
using ContainerClass = FP2PParticleContainerIndexed<FReal>;
using ContainerClass = FUserLeafContainer<FReal>;
//Typedefs :
using OctreeClass = FOctree<FReal,CoreCell,ContainerClass,LeafClass>;
......@@ -285,7 +294,7 @@ protected:
public:
FUserKernelEngine(/*int TreeHeight, double BoxWidth , double * BoxCenter, */scalfmm_kernel_type KernelType, scalfmm_algorithm algo) :
octree(nullptr), kernel(nullptr), upperLimit(2), treeHeight(0), boxCenter(0,0,0), boxCorner(0,0,0), boxWidth(0) /*,arranger(nullptr)*/ {
octree(nullptr), kernel(nullptr), upperLimit(2),treeHeight(0), boxCenter(0,0,0), boxCorner(0,0,0), boxWidth(0) /*,arranger(nullptr)*/ {
FScalFMMEngine<FReal>::kernelType = KernelType;
FScalFMMEngine<FReal>::Algorithm = algo;
}
......@@ -487,10 +496,27 @@ public:
currCell->setContainer(CoreCell::GetInit()(currLevel,currMorton,arrayCoord,position,generic_ptr));
}
});
//Then init leaves
octree->forEachCellLeaf([&](CoreCell * currCell, LeafClass * leaf){
FTreeCoordinate currCoord = currCell->getCoordinate();
int currLevel = octree->getHeight();
MortonIndex currMorton = currCoord.getMortonIndex(currLevel);
double position[3];
position[0] = boxCorner.getX() + currCoord.getX()*boxwidth/double(1<<currLevel);
position[1] = boxCorner.getY() + currCoord.getY()*boxwidth/double(1<<currLevel);
position[2] = boxCorner.getZ() + currCoord.getZ()*boxwidth/double(1<<currLevel);
leaf->getSrc()->setContainer(CoreCell::GetInitLeaf()(currLevel,leaf->getSrc()->getNbParticles(),
leaf->getSrc()->getIndexes().data(), currMorton,
position, currCell->getContainer(), this->kernel));
});
}
void free_cell(Callback_free_cell user_cell_deallocator){
void free_cell(Callback_free_cell user_cell_deallocator, Callback_free_leaf free_leaf){
octree->forEachCellLeaf([&](CoreCell * currCell, LeafClass * leaf){
free_leaf(currCell->getContainer(),leaf->getSrc()->getNbParticles(), leaf->getSrc()->getIndexes().data(),leaf,this->kernel);
});
octree->forEachCell([&](CoreCell * currCell){
if(currCell->getContainer()){
user_cell_deallocator(currCell->getContainer());
......@@ -640,7 +666,7 @@ public:
}
virtual void intern_dealloc_handle(Callback_free_cell userDeallocator){
free_cell(userDeallocator);
free_cell(userDeallocator, CoreCell::GetFreeLeaf());
}
};
......
// ===================================================================================
// Copyright ScalFmm 2014 I
// 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.
//
// 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.gnu.org/licenses".
// ===================================================================================
#ifndef FUSERLEAFCONTAINER_HPP
#define FUSERLEAFCONTAINER_HPP
/**
* @file This file contains a class that is an implementation of
* FParticleContainer, designed to be used by the User Kernel API.
*/
#include <Components/FBasicParticleContainer.hpp>
/**
* @author Piacibello
*
* @brief This class define another Particle Container, with dynamic
* (i.e. no template static) storage in order to store the user
* particles informations
*/
template<class FReal>
class FUserLeafContainer : public FP2PParticleContainerIndexed<FReal>{
void * userAttributes;
public:
FUserLeafContainer(const FUserLeafContainer&) = delete;
FUserLeafContainer& operator =(const FUserLeafContainer&) = delete;
FUserLeafContainer() : userAttributes(nullptr){
}
void setContainer(void * inputPtr){
userAttributes = inputPtr;
}
void * getContainer() const {
return userAttributes;
}
};
#endif // FUSERLEAFCONTAINER_HPP
......@@ -30,11 +30,27 @@ void cheb_free_cell(void * inCell){
ChebCellStruct_free(inCell);
}
/**
* No need for leaf function
*/
void * cheb_init_leaf(int level, FSize nbParts, const FSize * idxParts, long long morton_index, double center[3],
void * cellDatas, void * userDatas){
//Do nothing
return NULL;
}
/**
* No need for leaf function
*/
void cheb_free_leaf(void * cellDatas, FSize nbParts, const FSize * idxParts, void * leafData, void * userDatas){
//Do nothing
}
/**
* @brief Wrapper to FMM operators (refer to CScalfmmApi.h to get the
* detailed descriptions)
*/
void cheb_p2m(void* cellData, FSize nbParticlesInLeaf, const FSize* particleIndexes,
void cheb_p2m(void* cellData, void * leafData, FSize nbParticlesInLeaf, const FSize* particleIndexes,
void* userData){
ChebKernel_P2M(cellData,nbParticlesInLeaf,particleIndexes,userData);
}
......@@ -50,11 +66,12 @@ void cheb_l2l(int level, void* parentCell, int childPosition, void* childCell,
void* userData){
ChebKernel_L2L( level, parentCell, childPosition, childCell, userData);
}
void cheb_l2p(void* leafCell, FSize nbParticles, const FSize* particleIndexes,
void cheb_l2p(void* leafCell, void * leafData, FSize nbParticles, const FSize* particleIndexes,
void* userData){
ChebKernel_L2P( leafCell, nbParticles, particleIndexes, userData);
}
void cheb_p2pFull(FSize nbParticles, const FSize* particleIndexes,
void cheb_p2pFull(void * targetLeaf, FSize nbParticles, const FSize* particleIndexes,
void ** sourceLeaves,
const FSize ** sourceParticleIndexes, FSize* sourceNbPart,const int * sourcePosition,
const int size, void* userData) {
ChebKernel_P2P(nbParticles, particleIndexes, sourceParticleIndexes, sourceNbPart,sourcePosition,size,
......@@ -142,6 +159,8 @@ int main(int argc, char ** av){
struct User_Scalfmm_Cell_Descriptor cellDescriptor;
cellDescriptor.user_init_cell = cheb_init_cell;
cellDescriptor.user_free_cell = cheb_free_cell;
cellDescriptor.user_init_leaf = cheb_init_leaf;
cellDescriptor.user_free_leaf = cheb_free_leaf;
//Struct for ref cheb kernel
struct User_Scalfmm_Cell_Descriptor user_descr;
......
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