Commit 2e87dec4 authored by PIACIBELLO Cyrille's avatar PIACIBELLO Cyrille

Distributed API is functionnal, see testMpiUserKernel.c to get hindsight of how to use it

parent 31013676
......@@ -145,10 +145,9 @@ typedef void (*Callback_free_cell)(void*);
/**
* @brief Callback used to know the size of userData.
* @param level current level of current cell
* @param userData Datas that will be serialize
* @param morton_index of the current cell
*/
typedef FSize (*Callback_get_cell_size)(int level, void * userDatas, long long morton_index);
typedef FSize (*Callback_get_cell_size)(int level, long long morton_index);
/**
* @brief Callback used to serialize userdata inside an array of size
......@@ -159,6 +158,39 @@ typedef FSize (*Callback_get_cell_size)(int level, void * userDatas, long long m
*/
typedef void (*Callback_copy_cell)(void * userDatas, FSize size, void * memoryAllocated);
/**
* @brief Callback used by scalfmm to know the size needed by the user
* to store its local datas linked to a leaf.
*
* @param nbParts : number of point inside current Leaf
* @return Size (in bytes) needed to serialize the user datas
*/
typedef FSize (*Callback_get_leaf_size)(FSize nbParts);
/**
* @brief Callback used by scalfmm to serialize the leaf user data.
*
* @param Morton MortonIndex of current Leaf
* @param nbParts : number of point inside current Leaf
* @param userdata : leaf User data
* @param memAllocated : Ptr to an array of size =
* Callback_get_leaf_size(...), to be filled by the user.
*/
typedef void (*Callback_copy_leaf)(FSize nbParts, void * userDatas, void * memAllocated);
/**
* @brief Callback used by scalfmm to retreive leaf data from an array
* (previously filled by the user through Callback_copy_leaf)
*
* @param Morton MortonIndex of current Leaf
* @param nbParts : number of point inside current Leaf
* @param memAllocated : Ptr to an array of size =
* Callback_get_leaf_size(...), to be read by the user in order to
* re-build its leaf.
* @return new userdata local to the leaf
*/
typedef void * (*Callback_restore_leaf)(FSize nbParts, void * memAllocated);
/**
* @brief Callback called if scalfmm_finalize_cell is called.
......@@ -214,10 +246,18 @@ 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;
/**
* @brief This struct contains all the callback affecting leaves
*/
typedef struct User_Scalfmm_Leaf_Descriptor{
Callback_init_leaf user_init_leaf;
Callback_free_leaf user_free_leaf;
Callback_get_leaf_size user_get_size;
Callback_copy_leaf user_copy_leaf;
Callback_restore_leaf user_restore_leaf;
}Scalfmm_Leaf_Descriptor;
/**
* @brief This function build the tree. If scalfmm_init has been
......@@ -228,7 +268,10 @@ typedef struct User_Scalfmm_Cell_Descriptor{
* @param BoxWidth Width of the entire simulation box.
* @param BoxCenter Coordinate of the center of the box (ie array)
*/
void scalfmm_build_tree(scalfmm_handle handle,int TreeHeight,double BoxWidth,double* BoxCenter,Scalfmm_Cell_Descriptor user_cell_descriptor);
void scalfmm_build_tree(scalfmm_handle handle,int TreeHeight,double BoxWidth,
double* BoxCenter,
Scalfmm_Cell_Descriptor user_cell_descriptor,
Scalfmm_Leaf_Descriptor user_leaf_descriptor);
/**
......@@ -617,6 +660,29 @@ typedef void (*Callback_P2PInner)(void * targetLeaf,FSize nbParticles, const FSi
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 P2P Remote, the sources will
* be erased after the call, so no need to modify them
* @param targetLeaf ptr to user target leaf
* @param nbParticles number of particle in current leaf
* @param particleIndexes indexes of particles currently computed
* @praram sourceLeaves array of user source target
* @param sourceParticleIndexes array of indexes for each source
* @param sourceNbPart : array containing the number of part for each source
* @param size Number of direct neighbors
* @param userData datas specific to the user's kernel
* @attention This function will be called in distributed scalfmm
* only, between leaves belonging to diffenrent MPI processus. On ly
* the target leaf should be modified, since we don't send back the
* sources.
*/
typedef void (*Callback_P2PRemote)(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 method to reset a user's cell
* @param level level of the cell.
......@@ -647,6 +713,7 @@ typedef struct User_Scalfmm_Kernel_Descriptor {
Callback_P2PFull p2p_full;
Callback_P2PInner p2pinner;
Callback_P2PSym p2p_sym;
Callback_P2PRemote p2p_remote;
}Scalfmm_Kernel_Descriptor;
......@@ -778,8 +845,7 @@ scalfmm_handle scalfmm_init_distributed( scalfmm_kernel_type KernelType,scalfmm_
* once the partitionning done. Can be inserted with no changes.
* @param indexesFilled Array that store the global index of each part
* in the localArrayFilled.
* @param stride stride between two attributes inside attr.
* @param attr array of attribute to be distributed alongside the positions.
* @param outputNbPoint number of points dedicated to this proc
*/
void scalfmm_create_local_partition(scalfmm_handle handle, int nbPoints, double * particleXYZ, double ** localArrayFilled,
FSize ** indexesFilled, FSize * outputNbPoint);
......
......@@ -83,7 +83,8 @@ public:
FScalFMMEngine<FReal>::Algorithm = algo;
}
void build_tree(int TreeHeight, FReal BoxWidth , FReal * BoxCenter,User_Scalfmm_Cell_Descriptor notUsedHere){
virtual void build_tree(int TreeHeight, FReal BoxWidth , FReal * BoxCenter,
User_Scalfmm_Cell_Descriptor notUsedHere, Scalfmm_Leaf_Descriptor notUsedHereToo){
octree = new OctreeClass(TreeHeight,FMath::Min(3,TreeHeight-1),BoxWidth,FPoint<FReal>(BoxCenter));
this->matrix = new MatrixKernelClass();
this->kernel = new InterKernel(TreeHeight,BoxWidth,FPoint<FReal>(BoxCenter),matrix);
......
......@@ -95,7 +95,9 @@ public:
//by specific Engine
//Function about the tree
virtual void build_tree(int TreeHeight,FReal BoxWidth,FReal* BoxCenter,Scalfmm_Cell_Descriptor user_cell_descriptor){
virtual void build_tree(int TreeHeight,FReal BoxWidth,FReal* BoxCenter,
Scalfmm_Cell_Descriptor user_cell_descriptor,
Scalfmm_Leaf_Descriptor user_leaf_descriptor){
FAssertLF(0,"Nothing has been done yet, exiting");
}
......@@ -833,8 +835,11 @@ struct ScalFmmCoreHandle {
extern "C" void scalfmm_build_tree(scalfmm_handle Handle,int TreeHeight,double BoxWidth,double* BoxCenter,Scalfmm_Cell_Descriptor user_cell_descriptor){
((ScalFmmCoreHandle<double> *) Handle)->engine->build_tree(TreeHeight,BoxWidth, BoxCenter, user_cell_descriptor);
extern "C" void scalfmm_build_tree(scalfmm_handle Handle,int TreeHeight,double BoxWidth,
double* BoxCenter,
Scalfmm_Cell_Descriptor user_cell_descriptor,
Scalfmm_Leaf_Descriptor user_leaf_descriptor){
((ScalFmmCoreHandle<double> *) Handle)->engine->build_tree(TreeHeight,BoxWidth, BoxCenter, user_cell_descriptor, user_leaf_descriptor);
}
extern "C" void scalfmm_tree_insert_particles(scalfmm_handle Handle, int NbPositions, double * arrayX, double * arrayY, double * arrayZ,
......
This diff is collapsed.
This diff is collapsed.
......@@ -36,7 +36,15 @@ class FUserLeafContainer : public FP2PParticleContainerIndexed<FReal>{
void * userAttributes;
static Scalfmm_Leaf_Descriptor user_leaf_descriptor;
using Parent = FP2PParticleContainerIndexed<FReal>;
public:
static void Init(Scalfmm_Leaf_Descriptor leaf_descriptor){
user_leaf_descriptor = leaf_descriptor;
}
FUserLeafContainer(const FUserLeafContainer&) = delete;
FUserLeafContainer& operator =(const FUserLeafContainer&) = delete;
......@@ -51,6 +59,65 @@ public:
return userAttributes;
}
static Callback_init_leaf GetInitLeaf(){
return user_leaf_descriptor.user_init_leaf;
}
static Callback_free_leaf GetFreeLeaf(){
return user_leaf_descriptor.user_free_leaf;
}
/**
* @brief Functions to deal with serialization.
*
*/
template <class BufferWriterClass>
void save(BufferWriterClass& buffer) const{
Parent::template save<>(buffer);
if(user_leaf_descriptor.user_copy_leaf){
FSize nbPart = Parent::getNbParticles();
FSize sizeToSave = user_leaf_descriptor.user_get_size(nbPart);
char * temp = new char[sizeToSave];
user_leaf_descriptor.user_copy_leaf(nbPart,getContainer(),temp);
buffer.write(temp,sizeToSave);
delete [] temp;
}else{
std::cout<<"No user_copy_leaf function set\nExiting\n";
exit(0);
}
}
template <class BufferReaderClass>
void restore(BufferReaderClass& buffer){
Parent::template restore<>(buffer);
if(user_leaf_descriptor.user_restore_leaf){
FSize nbPart = Parent::getNbParticles();
FSize sizeToSave = user_leaf_descriptor.user_get_size(nbPart);
char * temp = new char[sizeToSave];
buffer.fillArray(temp,sizeToSave);
this->setContainer(user_leaf_descriptor.user_restore_leaf(nbPart,temp));
delete [] temp;
}else{
std::cout<<"No user_restore_leaf function set\nExiting\n";
exit(0);
}
}
FSize getSavedSize() const {
//Size of internal datas
FSize res = Parent::getSavedSize();
FSize userSize = 0;
if(!user_leaf_descriptor.user_get_size){
std::cout<<"No get_save_size function set\nExiting\n";
exit(0);
}else{
FSize nbPart = Parent::getNbParticles();
userSize = user_leaf_descriptor.user_get_size(nbPart);
res += userSize;
}
return res;
}
};
......
......@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <omp.h>
//For timing monitoring
#include "Timers.h"
......@@ -35,17 +36,14 @@ void cheb_free_cell(void * inCell){
*/
void * cheb_init_leaf(int level, FSize nbParts, const FSize * idxParts, long long morton_index, double center[3],
void * cellDatas, void * userDatas){
//Do nothing
int * A = malloc(sizeof(double) * nbParts);
return A;
return ChebLeafStruct_create(nbParts);
}
/**
* No need for leaf function
*/
void cheb_free_leaf(void * cellDatas, FSize nbParts, const FSize * idxParts, void * leafData, void * userDatas){
free(leafData);
//Do nothing
ChebLeafStruct_free(leafData);
}
/**
......@@ -54,7 +52,7 @@ void cheb_free_leaf(void * cellDatas, FSize nbParts, const FSize * idxParts, voi
*/
void cheb_p2m(void* cellData, void * leafData, FSize nbParticlesInLeaf, const FSize* particleIndexes,
void* userData){
ChebKernel_P2M(cellData,nbParticlesInLeaf,particleIndexes,userData);
ChebKernel_P2M(cellData,leafData,nbParticlesInLeaf,particleIndexes,userData);
}
void cheb_m2m(int level, void* parentCell, int childPosition, void* childCell,
void* userData){
......@@ -70,13 +68,13 @@ void cheb_l2l(int level, void* parentCell, int childPosition, void* childCell,
}
void cheb_l2p(void* leafCell, void * leafData, FSize nbParticles, const FSize* particleIndexes,
void* userData){
ChebKernel_L2P( leafCell, nbParticles, particleIndexes, userData);
ChebKernel_L2P( leafCell, leafData,nbParticles, particleIndexes, userData);
}
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,
ChebKernel_P2P(targetLeaf,nbParticles, particleIndexes, sourceLeaves, sourceParticleIndexes, sourceNbPart,sourcePosition,size,
userData);
}
......@@ -86,15 +84,46 @@ void cheb_resetCell(int level, long long morton_index, int* tree_position,
}
/**
* This function is mainly a display of its args...
* @brief From this point, the scalfmm leaves own the indexes, and
* each proc have its part partitionned, so we just need to copy our
* physical values (Vin) inside each leaf.
*/
void on_leaf(int level, FSize nbParts, const FSize * idxParts, long long morton_index, double center[3],
void * cellDatas, void * leafData, void * userDatas){
/* printf("I'm leaf at %lld pos, of center [%e %e %e], containing %lld parts\n", */
/* morton_index,center[0],center[1],center[2],nbParts); */
void fill_leaf_container(int level, FSize nbParts, const FSize * idxParts,
long long morton_index, double center[3],
void * cellDatas,void * leafData, void * userDatas){
ChebLeafStruct_fill(nbParts,idxParts,morton_index,leafData,userDatas);
}
/**
* @brief this function store the results gathered across the leaves
* to store it inside force computed arrays.
*/
void get_results_from_leaves(int level, FSize nbParts, const FSize * idxParts, long long morton_index, double center[3],
void * cellDatas, void * leafData, void * userDatas){
UserData * ptrToUserData = (UserData*) userDatas;
double * forceX = NULL;
double ** forceXPtr = &forceX;
double * forceY = NULL;
double ** forceYPtr = &forceY;
double * forceZ = NULL;
double ** forceZPtr = &forceZ;
double * potentials = NULL;
double ** potPtr = &potentials;
ChebLeafStruct_get_back_results(leafData,forceXPtr,forceYPtr,forceZPtr,potPtr);
for(int i=0 ; i<nbParts ; ++i){
//index of the part
int idx = idxParts[i];
//force on X axis
ptrToUserData->forcesComputed[0][3*idx+0] = forceX[i];
ptrToUserData->forcesComputed[0][3*idx+1] = forceY[i];
ptrToUserData->forcesComputed[0][3*idx+2] = forceZ[i];
ptrToUserData->potentials[0][idx] = potentials[i];
}
}
/**
* @brief Do everything
......@@ -158,20 +187,24 @@ 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 User_Scalfmm_Leaf_Descriptor user_descr_leaf;
user_descr_leaf.user_init_leaf = cheb_init_leaf;
user_descr_leaf.user_free_leaf = cheb_free_leaf;
//should not be checked, but nullify just in case.
user_descr_leaf.user_get_size = NULL;
user_descr_leaf.user_copy_leaf = NULL;
user_descr_leaf.user_restore_leaf = NULL;
//Struct for ref cheb kernel
struct User_Scalfmm_Cell_Descriptor user_descr;
user_descr.user_init_cell = NULL;
user_descr.user_free_cell = NULL;
// Init tree and cell
printf("Building the tree and Initizalizing the cells:\n");
scalfmm_build_tree(handle,treeHeight, boxWidth, boxCenter, cellDescriptor);
scalfmm_build_tree(handle_ref,treeHeight, boxWidth, boxCenter, user_descr);
scalfmm_build_tree(handle_ref,treeHeight, boxWidth, boxCenter, user_descr , user_descr_leaf);
scalfmm_build_tree(handle,treeHeight, boxWidth, boxCenter, cellDescriptor,user_descr_leaf);
//Once is the tree built, one must set the kernel before inserting particles
......@@ -179,15 +212,17 @@ int main(int argc, char ** av){
struct User_Scalfmm_Kernel_Descriptor kernel;
kernel.p2m = cheb_p2m;
kernel.m2m = cheb_m2m;
//init the other to NULL
kernel.m2l = NULL;
kernel.m2l_full = cheb_m2l_full;
kernel.l2l = cheb_l2l;
kernel.l2p = cheb_l2p;
kernel.p2p_sym = NULL;
kernel.p2p_full = cheb_p2pFull;
//init the other to NULL
kernel.m2l = NULL;
kernel.p2p_sym = NULL;
kernel.p2pinner = NULL;
kernel.p2p = NULL;
kernel.m2m_full = NULL;
kernel.l2l_full = NULL;
//Set my datas
UserData userDatas;
......@@ -247,7 +282,7 @@ int main(int argc, char ** av){
while(ite<max_ite){
//Execute FMM
scalfmm_apply_on_leaf(handle,on_leaf);
scalfmm_apply_on_leaf(handle,fill_leaf_container);
tic(&interface_timer);
scalfmm_execute_fmm(handle/*, kernel, &my_data*/);
......@@ -256,6 +291,7 @@ int main(int argc, char ** av){
{ //Temporary
int nbTimers = scalfmm_get_nb_timers(handle);
double * timersArray = malloc(sizeof(double)*nbTimers);
memset(timersArray,0,sizeof(double)*nbTimers);
scalfmm_get_timers(handle,timersArray);
int i;
for(i=0; i<nbTimers ; ++i){
......@@ -298,7 +334,6 @@ int main(int argc, char ** av){
/* free(timersArray); */
/* } */
printf("Intern Chebyshev done\n");
print_elapsed(&ref_timer);
......@@ -316,6 +351,12 @@ int main(int argc, char ** av){
scalfmm_get_potentials(handle_ref,nbPart,potentialsRef,BOTH);
//scalfmm_print_everything(handle_ref);
{
//Copy results from the leaves inside forcesToStore.
scalfmm_apply_on_leaf(handle,get_results_from_leaves);
}
{//Comparison part
FSize idxPart;
int nbPartOkay = 0;
......
......@@ -172,7 +172,6 @@ int main(int argc, char ** av){
double* particleXYZ = malloc(sizeof(double)*3*nbPart);
double* physicalValues = malloc(sizeof(double)*nbPart);
{
printf("Creating Particles:\n");
FSize idxPart;
......@@ -207,12 +206,17 @@ int main(int argc, char ** av){
struct User_Scalfmm_Cell_Descriptor cellDescriptor;
cellDescriptor.user_init_cell = displ_init_cell;
cellDescriptor.user_free_cell = displ_free_cell;
struct User_Scalfmm_Leaf_Descriptor user_descr_leaf;
user_descr_leaf.user_init_leaf = NULL;
user_descr_leaf.user_free_leaf = NULL;
user_descr_leaf.user_get_size = NULL;
user_descr_leaf.user_copy_leaf = NULL;
user_descr_leaf.user_restore_leaf = NULL;
// Init tree and cell
printf("Building the tree and Initizalizing the cells:\n");
scalfmm_build_tree(handle,treeHeight, boxWidth, boxCenter, cellDescriptor);
scalfmm_build_tree(handle,treeHeight, boxWidth, boxCenter, cellDescriptor, user_descr_leaf);
//Once is the tree built, one must set the kernel before inserting particles
......@@ -220,12 +224,15 @@ int main(int argc, char ** av){
struct User_Scalfmm_Kernel_Descriptor kernel;
kernel.p2m = displ_p2m;
kernel.m2m = displ_m2m;
kernel.m2m_full = NULL;
//init the other to NULL
kernel.m2l = NULL;
kernel.m2l_full = displ_m2l_full;
kernel.l2l = displ_l2l;
kernel.l2l_full = NULL;
kernel.l2p = displ_l2p;
kernel.p2p_full = displ_p2pFull;
kernel.p2p_sym = NULL;
kernel.p2pinner = NULL;
kernel.p2p = NULL;
......@@ -277,6 +284,7 @@ int main(int argc, char ** av){
scalfmm_dealloc_handle(handle,displ_free_cell);
free(particleXYZ);
free(physicalValues);
return EXIT_SUCCESS;
}
......@@ -33,19 +33,39 @@ void cheb_free_cell(void * inCell){
ChebCellStruct_free(inCell);
}
/**
* @brief Wrapper to init a Cheb Leaf
*/
void * cheb_init_leaf(int level, FSize nbParts, const FSize * idxParts,
long long morton_index,double llc[3], void * cellDatas,
void * userDatas){
//TODO
return ChebLeafStruct_create(nbParts);
}
/**
* @brief Wrapper to free a Cheb Leaf
*/
void cheb_free_leaf(void * cellDatas, FSize nbPart, const FSize * idxParts, void * leafData,
void * userDatas){
//TODO
ChebLeafStruct_free(leafData);
}
/**
* @brief Wrapper to FMM operators (refer to CScalfmmApi.h to get the
* detailed descriptions)
*/
void cheb_p2m(void* cellData,void * leafData, 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);
ChebKernel_P2M(cellData,leafData,nbParticlesInLeaf,particleIndexes,userData);
}
void cheb_m2m(int level, void* parentCell, int childPosition, void* childCell,
void* userData){
ChebKernel_M2M(level,parentCell,childPosition,childCell,userData);
}
void cheb_m2l_full(int level, void* targetCell,const int* neighborPosition, const int size, void** sourceCell,
void cheb_m2l_full(int level, void* targetCell,const int* neighborPosition,
const int size, void** sourceCell,
void* userData){
ChebKernel_M2L(level, targetCell, neighborPosition, size, sourceCell, userData);
}
......@@ -53,16 +73,26 @@ void cheb_l2l(int level, void* parentCell, int childPosition, void* childCell,
void* userData){
ChebKernel_L2L( level, parentCell, childPosition, childCell, userData);
}
void cheb_l2p(void* cellData, void* leafData, FSize nbParticles, const FSize* particleIndexes,
void cheb_l2p(void* cellData, void* leafData, FSize nbParticles,
const FSize* particleIndexes,
void* userData){
ChebKernel_L2P( cellData, nbParticles, particleIndexes, userData);
ChebKernel_L2P( cellData, leafData, nbParticles, particleIndexes, userData);
}
void cheb_p2pFull(void * targetLeaf, FSize nbParticles, const FSize* particleIndexes,
void ** sourceLeaves,
const FSize ** sourceParticleIndexes, FSize* sourceNbPart,const int * sourcePosition,
const FSize ** sourceParticleIndexes, FSize* sourceNbPart,
const int * sourcePosition,
const int size, void* userData) {
ChebKernel_P2P(nbParticles, particleIndexes, sourceParticleIndexes, sourceNbPart,sourcePosition,size,
userData);
ChebKernel_P2P(targetLeaf,nbParticles, particleIndexes, sourceLeaves,sourceParticleIndexes,
sourceNbPart,sourcePosition,size, userData);
}
void cheb_p2p_remote(void * targetLeaf,FSize nbParticles, const FSize* particleIndexes,
void ** sourceLeaves,
const FSize ** sourceParticleIndexes,FSize * sourceNbPart,
const int * sourcePosition, const int size, void* userData){
ChebKernel_P2PRemote(targetLeaf,nbParticles, particleIndexes, sourceLeaves,sourceParticleIndexes,
sourceNbPart,sourcePosition,size, userData);
}
void cheb_resetCell(int level, long long morton_index, int* tree_position,
......@@ -71,8 +101,12 @@ void cheb_resetCell(int level, long long morton_index, int* tree_position,
spatial_position,userCell,userData);
}
FSize cheb_get_size(int level,void * userData, long long morton_index){
return ChebCell_getSize(level,userData,morton_index);
/**
* @brief Following functions are defined in order to serialize the
* cells
*/
FSize cheb_get_size(int level, long long morton_index){
return ChebCell_getSize(level,morton_index);
}
void cheb_copy_cell(void * userDatas, FSize size, void * memoryAllocated){
......@@ -83,22 +117,68 @@ void * cheb_restore_cell(int level, void * arrayTobeRead){
return ChebCell_restore(level,arrayTobeRead);
}
void on_leaf(int level, FSize nbParts, const FSize * idxParts, long long morton_index, double center[3],
void * cellDatas,void * leafdata, void * userDatas){
/**
* @brief Following functions are defined in order to serialize the
* leaves
*/
FSize cheb_get_leaf_size(FSize nbPart){
return ChebLeaf_getSize(nbPart);
}
void cheb_copy_leaf(FSize nbPart, void * userdata, void * memAllocated){
ChebLeaf_copy(nbPart,userdata,memAllocated);
}
void* cheb_restore_leaf(FSize nbPart, void * memToRead){
return ChebLeaf_restore(nbPart,memToRead);
}
/**
* @brief From this point, the scalfmm leaves own the indexes, and
* each proc have its part partitionned, so we just need to copy our
* physical values (Vin) inside each leaf.
*/
void fill_leaf_container(int level, FSize nbParts, const FSize * idxParts,
long long morton_index, double center[3],
void * cellDatas,void * leafData, void * userDatas){
ChebLeafStruct_fill(nbParts,idxParts,morton_index,leafData,userDatas);
}
/**
* @brief This function compute the total energy for each proc.
*/
void on_leaf(int level, FSize nbParts, const FSize * idxParts, long long morton_index, double center[3],
void * cellDatas,void * leafData, void * userDatas){
UserData * ptrToUserData = (UserData*) userDatas;
//Compute totalEnergy
int nbThread = omp_get_max_threads();
int i,j;
for( i=0 ; i<nbParts ; ++i){
double pot = 0.0;
//Small loop over the different arrays
for( j=0 ; j<nbThread ; ++j){
pot += ptrToUserData->potentials[j][idxParts[i]];
/* for( i=0 ; i<nbParts ; ++i){ */
/* double pot = 0.0; */
/* //Small loop over the different arrays */
/* for( j=0 ; j<nbThread ; ++j){ */
/* pot += ptrToUserData->potentials[j][idxParts[i]]; */
/* } */
/* ptrToUserData->totalEnergy += pot*(ptrToUserData->myPhyValues[idxParts[i]]); */
/* } */
if(leafData){
double * forceX = NULL;
double ** forceXPtr = &forceX;
double * forceY = NULL;
double ** forceYPtr = &forceY;
double * forceZ = NULL;
double ** forceZPtr = &forceZ;
double * potentials = NULL;
double ** potPtr = &potentials;
ChebLeafStruct_get_back_results(leafData,forceXPtr,forceYPtr,forceZPtr,potPtr);
double pot = 0;
for(int i=0 ; i<nbParts ; ++i){
pot += potentials[i];
}
ptrToUserData->totalEnergy += pot*(ptrToUserData->myPhyValues[idxParts[i]]);
}
/* printf("I'm leaf at %lld pos, of center [%e %e %e], containing %lld parts\n", */
/* morton_index,center[0],center[1],center[2],nbParts); */
......@@ -177,19 +257,30 @@ int main(int argc, char ** argv){
cellDescriptor.user_copy_cell = cheb_copy_cell;
cellDescriptor.user_restore_cell = cheb_restore_cell;
struct User_Scalfmm_Leaf_Descriptor leafDecriptor;
leafDecriptor.user_init_leaf = cheb_init_leaf;
leafDecriptor.user_free_leaf = cheb_free_leaf;
leafDecriptor.user_get_size = cheb_get_leaf_size;
leafDecriptor.user_copy_leaf = cheb_copy_leaf;
leafDecriptor.user_restore_leaf = cheb_restore_leaf;
//Set our callbacks
struct User_Scalfmm_Kernel_Descriptor kernel;
kernel.p2m = cheb_p2m;
kernel.m2m = cheb_m2m;
kernel.m2m_full = NULL;
//init the other to NULL
kernel.m2l = NULL;
kernel.m2l_ext = NULL;
kernel.m2l_full = cheb_m2l_full;
kernel.l2l = cheb_l2l;
kernel.l2l_full = NULL;
kernel.l2p = cheb_l2p;
kernel.p2p_sym = NULL;
kernel.p2p_full = cheb_p2pFull;
kernel.p2pinner = NULL;
kernel.p2p = NULL;
kernel.p2p_remote = cheb_p2p_remote;
//Set my datas
UserData userDatas;
......@@ -197,7 +288,8 @@ int main(int argc, char ** argv){
//Give ScalFMM the datas before calling fmm (this will set as well the kernel)
scalfmm_user_kernel_config(Handle,kernel,&userDatas);
scalfmm_build_tree(Handle,treeHeight, boxWidth, boxCenter, cellDescriptor);
scalfmm_build_tree(Handle,treeHeight, boxWidth, boxCenter,
cellDescriptor, leafDecriptor);
printf("Tree built.\n");
double * outputArray; //Will be allocated inside create_local_partition
......@@ -250,12 +342,16 @@ int main(int argc, char ** argv){
printf("Insertion done, I'm process %d, and have inserted %lld parts.\n",my_rank,outputNbPoint);
//Asking ScalFMM to partition physicalValues too
scalfmm_generic_partition(Handle,nbPart,sizeof(physicalValues[0]),physicalValues,outputPhyValPtr);
printf("[%d] Generic Partition Done ! \n",my_rank);
userDatas.myPhyValues = outputPhyVal;
//There we used a for each leaf method to initialize our leaf containers.