Commit 5c67f64e authored by PIACIBELLO Cyrille's avatar PIACIBELLO Cyrille

Api is almost finished, new test added in order to test the user kernel interface

parent 3d3be250
......@@ -362,7 +362,7 @@ typedef void (*Callback_L2L)(int level, void* parentCell, int childPosition, voi
* @param particleIndexes indexes of particles currently computed
* @param userData datas specific to the user's kernel
*/
typedef void (*Callback_L2P)(void* leafCell, int nbParticles, int* particleIndexes, void* userData);
typedef void (*Callback_L2P)(void* leafCell, int nbParticles,const int* particleIndexes, void* userData);
/**
* @brief Function to be filled by user's P2P
......@@ -380,7 +380,7 @@ typedef void (*Callback_P2P)(int nbParticles, const int* particleIndexes, int nb
* @param particleIndexes indexes of particles currently computed
* @param userData datas specific to the user's kernel
*/
typedef void (*Callback_P2PInner)(int nbParticles, int* particleIndexes, void* userData);
typedef void (*Callback_P2PInner)(int nbParticles, const int* particleIndexes, void* userData);
......@@ -434,6 +434,10 @@ typedef void* (*Callback_init_cell)(int level, long long morton_index, int* tree
typedef void (*Callback_free_cell)(void*);
void scalfmm_init_cell(scalfmm_handle Handle, Callback_init_cell user_cell_initializer);
void scalfmm_free_cell(scalfmm_handle Handle, Callback_free_cell user_cell_deallocator);
///////////////// Common kernel part : /////////////////
......
......@@ -67,11 +67,12 @@ public:
* @param BoxCenter double[3] coordinate of the center of the
* simulation box
*/
FInterEngine(int TreeHeight, double BoxWidth , double * BoxCenter) : kernel(nullptr), matrix(nullptr), octree(nullptr),arranger(nullptr){
FInterEngine(int TreeHeight, double BoxWidth , double * BoxCenter,scalfmm_kernel_type KernelType) :
kernel(nullptr), matrix(nullptr), octree(nullptr),arranger(nullptr){
octree = new OctreeClass(TreeHeight,FMath::Min(3,TreeHeight-1),BoxWidth,FPoint(BoxCenter));
this->matrix = new MatrixKernelClass();
this->kernel = new InterKernel(TreeHeight,BoxWidth,FPoint(BoxCenter),matrix);
kernelType = chebyshev;
kernelType = KernelType;
arranger = nullptr;
}
......
......@@ -56,7 +56,6 @@ protected:
public:
FScalFMMEngine() : Algorithm(multi_thread), progress(), nbPart(0){
//Default behavior in case of out of the box particles is exiting
}
//First function displayed there are common function for every
......@@ -197,6 +196,14 @@ public:
FAssertLF(0,"No user kernel defined, exiting ...\n");
}
virtual void init_cell(Callback_init_cell user_cell_initializer){
FAssertLF(0,"No user kernel defined, exiting ...\n");
}
virtual void free_cell(Callback_free_cell user_cell_initializer){
FAssertLF(0,"No user kernel defined, exiting ...\n");
}
virtual void execute_fmm(){
FAssertLF(0,"No kernel set, cannot execute anything, exiting ...\n");
}
......@@ -371,6 +378,13 @@ extern "C" void scalfmm_execute_fmm(scalfmm_handle Handle){
((ScalFmmCoreHandle * ) Handle)->engine->execute_fmm();
}
extern "C" void scalfmm_init_cell(scalfmm_handle Handle, Callback_init_cell user_cell_initializer){
((ScalFmmCoreHandle * ) Handle)->engine->init_cell(user_cell_initializer);
}
extern "C" void scalfmm_free_cell(scalfmm_handle Handle, Callback_free_cell user_cell_deallocator){
((ScalFmmCoreHandle * ) Handle)->engine->free_cell(user_cell_deallocator);
}
#endif
......@@ -8,6 +8,7 @@ extern "C" {
}
#include "FInterEngine.hpp"
#include "FUserKernelEngine.hpp"
extern "C" scalfmm_handle scalfmm_init(int TreeHeight,double BoxWidth,double* BoxCenter, scalfmm_kernel_type KernelType){
ScalFmmCoreHandle * handle = new ScalFmmCoreHandle();
......@@ -26,7 +27,7 @@ extern "C" scalfmm_handle scalfmm_init(int TreeHeight,double BoxWidth,double* Bo
typedef FInterpMatrixKernelR MatrixKernelClass;
typedef FChebSymKernel<ChebCell,ContainerClass,MatrixKernelClass,7> ChebKernel;
handle->engine = new FInterEngine<ChebCell,ChebKernel>(TreeHeight,BoxWidth,BoxCenter);
handle->engine = new FInterEngine<ChebCell,ChebKernel>(TreeHeight,BoxWidth,BoxCenter, KernelType);
break;
case 2:
//TODO typedefs
......@@ -36,7 +37,7 @@ extern "C" scalfmm_handle scalfmm_init(int TreeHeight,double BoxWidth,double* Bo
typedef FInterpMatrixKernelR MatrixKernelClass;
typedef FUnifKernel<UnifCell,ContainerClass,MatrixKernelClass,7> UnifKernel;
handle->engine = new FInterEngine<UnifCell,UnifKernel>(TreeHeight,BoxWidth,BoxCenter);
handle->engine = new FInterEngine<UnifCell,UnifKernel>(TreeHeight,BoxWidth,BoxCenter,KernelType);
break;
default:
......
// ===================================================================================
// 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".
// ===================================================================================
/**
* @file This file contains a class that inherits from FScalFMMEngine,
* and will implement the API functions for a user defined kernel.
*/
#ifndef FUSERKERNELENGINE_HPP
#define FUSERKERNELENGINE_HPP
#include "FScalFMMEngine.hpp"
/**
* @brief CoreCell : Cell used to store User datas
*/
class CoreCell : public FBasicCell {
// Mutable in order to work with the API
mutable void* userData;
public:
CoreCell() : userData(nullptr) {
}
~CoreCell(){
}
/**
* @brief setContainer store the ptr to the user data inside our
* struct
*/
void setContainer(void* inContainer) const {
userData = inContainer;
}
/**
* @brief getContainer : return the user datas (in order to give
* it back to the user defined kernel function)
*/
void* getContainer() const {
return userData;
}
};
/**
* This class simply call the function pointers from Scalfmm_Kernel_Descriptor.
* If not pointer is set the calls are skipped.
* The userData is given at any calls.
*/
template< class CellClass, class ContainerClass>
class CoreKernel : public FAbstractKernels<CellClass,ContainerClass> {
Scalfmm_Kernel_Descriptor kernel;
void* userData;
public:
CoreKernel(Scalfmm_Kernel_Descriptor inKernel, void* inUserData) : kernel(inKernel) , userData(inUserData){
}
/** Default destructor */
virtual ~CoreKernel(){
}
/** 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);
}
/** Do nothing */
virtual void M2M(CellClass* const FRestrict cell, const CellClass*const FRestrict *const FRestrict children, const int level) {
if(kernel.m2m){
for(int idx = 0 ; idx < 8 ; ++idx){
if( children[idx] ){
kernel.m2m(level, cell->getContainer(), idx, children[idx]->getContainer(), userData);
}
}
}
}
/** Do nothing */
virtual void M2L(CellClass* const FRestrict cell, const CellClass* interactions[], const int , const int level) {
if(kernel.m2l){
for(int idx = 0 ; idx < 343 ; ++idx){
if( interactions[idx] ){
kernel.m2l(level, cell->getContainer(), idx, interactions[idx]->getContainer(), userData);
}
}
}
}
/** Do nothing */
virtual void L2L(const CellClass* const FRestrict cell, CellClass* FRestrict *const FRestrict children, const int level) {
if(kernel.l2l){
for(int idx = 0 ; idx < 8 ; ++idx){
if( children[idx] ){
kernel.l2l(level, cell->getContainer(), idx, children[idx]->getContainer(), userData);
}
}
}
}
/** Do nothing */
virtual void L2P(const CellClass* const cell, ContainerClass* const container){
if(kernel.l2p) kernel.l2p(cell->getContainer(), container->getNbParticles(), container->getIndexes().data(), userData);
}
/** Do nothing */
virtual void P2P(const FTreeCoordinate& ,
ContainerClass* const FRestrict targets, const ContainerClass* const FRestrict /*sources*/,
ContainerClass* const neighbors[27], const int ){
if(kernel.p2pinner) kernel.p2pinner(targets->getNbParticles(), targets->getIndexes().data(), userData);
if(kernel.p2p){
for(int idx = 0 ; idx < 27 ; ++idx){
if( neighbors[idx] ){
kernel.p2p(targets->getNbParticles(), targets->getIndexes().data(),
neighbors[idx]->getNbParticles(), neighbors[idx]->getIndexes().data(), userData);
}
}
}
}
/** Do nothing */
virtual void P2PRemote(const FTreeCoordinate& ,
ContainerClass* const FRestrict , const ContainerClass* const FRestrict ,
ContainerClass* const [27], const int ){
}
};
class FUserKernelEngine : public FScalFMMEngine{
private:
//Typedefs :
typedef FP2PParticleContainerIndexed<> ContainerClass;
typedef FSimpleLeaf<ContainerClass> LeafClass;
typedef FOctree<CoreCell,ContainerClass,LeafClass> OctreeClass;
typedef CoreKernel<CoreCell,ContainerClass> CoreKernelClass;
typedef FP2PLeafInterface<OctreeClass> LeafInterface;
//For arranger classes
typedef FOctreeArranger<OctreeClass,ContainerClass,LeafInterface> ArrangerClass;
typedef FArrangerPeriodic<OctreeClass,ContainerClass,LeafInterface> ArrangerClassPeriodic;
//Attributes
OctreeClass * octree;
CoreKernelClass * kernel;
ArrangerClass * arranger;
public:
FUserKernelEngine(int TreeHeight, double BoxWidth , double * BoxCenter, scalfmm_kernel_type KernelType) :
octree(nullptr), kernel(nullptr), arranger(nullptr){
octree = new OctreeClass(TreeHeight,FMath::Min(3,TreeHeight-1),BoxWidth,FPoint(BoxCenter));
kernelType = KernelType;
//Kernel is not set now because the user must provide a
//Scalfmm_Kernel_descriptor
//kernel = new CoreKernelClass();
}
void user_kernel_config( Scalfmm_Kernel_Descriptor userKernel, void * userDatas){
kernel = new CoreKernelClass(userKernel,userDatas);
}
void tree_insert_particles( int NbPositions, double * arrayX, double * arrayY, double * arrayZ){
for(int idPart = 0; idPart<NbPositions ; ++idPart){
octree->insert(FPoint(arrayX[idPart],arrayY[idPart],arrayZ[idPart]),idPart);
}
nbPart += NbPositions;
}
void tree_insert_particles_xyz( int NbPositions, double * XYZ){
for(int idPart = 0; idPart<NbPositions ; ++idPart){
octree->insert(FPoint(&XYZ[3*idPart]),idPart);
}
nbPart += NbPositions;
}
/*
* Call the user allocator on userDatas member field of each cell
*/
void init_cell(Callback_init_cell user_cell_initializer){
if(user_cell_initializer){
double boxwidth = octree->getBoxWidth();
FPoint BoxCenter = octree->getBoxCenter();
double boxCorner[3];
boxCorner[0] = BoxCenter.getX() - boxwidth/2.0;
boxCorner[1] = BoxCenter.getY() - boxwidth/2.0;
boxCorner[2] = BoxCenter.getZ() - boxwidth/2.0;
//apply user function on each cell
octree->forEachCellWithLevel([&](CoreCell * currCell,const int currLevel){
FTreeCoordinate currCoord = currCell->getCoordinate();
int arrayCoord[3] = {currCoord.getX(),currCoord.getY(),currCoord.getZ()};
MortonIndex currMorton = currCoord.getMortonIndex(currLevel);
double position[3];
position[0] = boxCorner[0] + currCoord.getX()*boxwidth/double(1<<currLevel);
position[1] = boxCorner[1] + currCoord.getY()*boxwidth/double(1<<currLevel);
position[2] = boxCorner[2] + currCoord.getZ()*boxwidth/double(1<<currLevel);
currCell->setContainer(user_cell_initializer(currLevel,currMorton,arrayCoord,position));
});
}
}
void free_cell(Callback_free_cell user_cell_deallocator){
octree->forEachCell([&](CoreCell * currCell){
user_cell_deallocator(currCell->getContainer());
});
}
void execute_fmm(){
//FAssertLF(kernel,"No kernel set, please use scalfmm_user_kernel_config before calling the execute routine ... Exiting \n");
switch(Algorithm){
case 0:
{
typedef FFmmAlgorithm<OctreeClass,CoreCell,ContainerClass,CoreKernelClass,LeafInterface> AlgoClassSeq;
AlgoClassSeq algoSeq(octree,kernel);
algoSeq.execute();
break;
}
case 1:
{
typedef FFmmAlgorithmThread<OctreeClass,CoreCell,ContainerClass,CoreKernelClass,LeafClass> AlgoClassThread;
AlgoClassThread algoThread(octree,kernel);
algoThread.execute();
break;
}
case 2:
{
typedef FFmmAlgorithmPeriodic<OctreeClass,CoreCell,ContainerClass,CoreKernelClass,LeafClass> AlgoClassPeriodic;
AlgoClassPeriodic algoPeriod(octree,2);
algoPeriod.setKernel(kernel);
algoPeriod.execute();
break;
}
default :
std::cout<< "No algorithm found (probably for strange reasons) : "<< Algorithm <<" exiting" << std::endl;
}
}
};
#endif //FUSERKERNELENGINE_HPP
This diff is collapsed.
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