From aa4c4d19dba73babdec529d2347f11abdbd6d7c9 Mon Sep 17 00:00:00 2001
From: piacibel <cyrille.piacibello@inria.fr>
Date: Mon, 17 Nov 2014 18:58:06 +0100
Subject: [PATCH] API can now call chebyshev/lagrange kernel succesfully (only
 cheb has been tested), remaining to do : updates positions of particles

---
 Addons/CKernelApi/Src/CScalfmmApi.h      |  47 ++-
 Addons/CKernelApi/Src/FInterEngine.hpp   | 347 ++++++++++++++++++++++-
 Addons/CKernelApi/Src/FScalFMMEngine.hpp |  64 ++++-
 3 files changed, 434 insertions(+), 24 deletions(-)

diff --git a/Addons/CKernelApi/Src/CScalfmmApi.h b/Addons/CKernelApi/Src/CScalfmmApi.h
index 7bbafc8f5..2f47c875b 100644
--- a/Addons/CKernelApi/Src/CScalfmmApi.h
+++ b/Addons/CKernelApi/Src/CScalfmmApi.h
@@ -68,6 +68,29 @@ typedef enum kernel_type {
 } scalfmm_kernel_type;
 
 
+/**
+ * Enum over the different way scalfmm can handle a particule moving
+ * out of the simulation box
+ */
+typedef enum out_of_the_box_config {
+    exiting = 0,  /*If a particule move outside the simulation box,
+                    the simulation stop*/
+    periodic = 1, /*If a particule move outside the simulation box,
+                    the particules is inserted back at the other side
+                    of the simulation box*/
+    erasing = 2   /*If a particule move outside the simulation box, it
+                    simply disappears from the simulation */
+} scalfmm_out_of_box_behavior;
+
+/**
+ * Enum over the different algorithm that scalfmm can use
+ */
+typedef enum scalfmm_algorithm_config {
+    sequential = 0,  /* Use the sequential version of Scalfmm*/
+    multi_thread = 1 /* Use the Multi thread version of Scalfmm*/
+} scalfmm_algorithm;
+
+
 /**
  * Handle for the user
  */
@@ -135,6 +158,11 @@ void scalfmm_tree_insert_particles_xyz(scalfmm_handle Handle, int NbPositions, d
  * the array. First particle inserted will take value physicalValues[0].
  */
 void scalfmm_set_physical_values(scalfmm_handle Handle, int nbPhysicalValues, double * physicalValues);
+/**
+ * @brief get the physical values.
+ *
+ * WARNING : the user must allocate (and initialize) the array given
+ */
 void scalfmm_get_physical_values(scalfmm_handle Handle, int nbPhysicalValues, double * physicalValues);
 
 /**
@@ -206,7 +234,7 @@ void scalfmm_set_forces_npart(scalfmm_handle Handle, int nbParts, int* idxOfPart
  * array.
  */
 void scalfmm_get_potentials(scalfmm_handle Handle, int nbParts, double * potentialsToFill);
-void scalfmm_set_potentials(scalfmm_handle Handle, int nbParts, double * potentialsToFill);
+void scalfmm_set_potentials(scalfmm_handle Handle, int nbParts, double * potentialsToRead);
 void scalfmm_get_potentials_npart(scalfmm_handle Handle, int nbParts, int* idxOfParticles, double * potentialsToFill);
 void scalfmm_set_potentials_npart(scalfmm_handle Handle, int nbParts, int* idxOfParticles, double * potentialsToFill);
 
@@ -251,7 +279,24 @@ void scalfmm_get_positions(scalfmm_handle Handle, int NbPositions, double * X, d
 void scalfmm_get_positions_xyz_npart(scalfmm_handle Handle, int NbPositions, int* idxOfParticles, double * updatedXYZ);
 void scalfmm_get_positions_npart(scalfmm_handle Handle, int NbPositions, int* idxOfParticles, double * X, double * Y , double * Z);
 
+/**
+ * @brief This function provides a way for the user to define scalfmm
+ * behavior in case a particule get out of the box after a
+ * displacement
+ * @param  Handle scalfmm_handle provided by scalfmm_init
+ * @param  Member of enum scalfmm_out_of_box_behavior
+ */
+
+void scalfmm_out_of_the_box_config(scalfmm_handle Handle,scalfmm_out_of_box_behavior config);
+
+/**
+ * @brief This function provides a way for choosing the algorithm to
+ * be used
+ * @param  Handle scalfmm_handle provided by scalfmm_init
+ * @param  Member of enum scalfmm_algorithm
+ */
 
+void scalfmm_algorithm_config(scalfmm_handle Handle,scalfmm_algorithm config);
 
 
 /////////////////////////////////////////////////////////////////////
diff --git a/Addons/CKernelApi/Src/FInterEngine.hpp b/Addons/CKernelApi/Src/FInterEngine.hpp
index bfe85933e..d5b6d3c75 100644
--- a/Addons/CKernelApi/Src/FInterEngine.hpp
+++ b/Addons/CKernelApi/Src/FInterEngine.hpp
@@ -25,11 +25,10 @@
 #include "FScalFMMEngine.hpp"
 #include "Kernels/Interpolation/FInterpMatrixKernel.hpp"
 
-#ifdef _OPENMP
+
 #include "Core/FFmmAlgorithmThread.hpp"
-#else
 #include "Core/FFmmAlgorithm.hpp"
-#endif
+
 
 
 /**
@@ -38,31 +37,363 @@
  */
 template<class InterCell,class InterKernel,
          class ContainerClass = FP2PParticleContainerIndexed<>,
-         class LeafClass = FSimpleLeaf<FP2PParticleContainerIndexed<>>,
+         class LeafClass = FSimpleLeaf<FP2PParticleContainerIndexed<> >,
          class MatrixKernelClass = FInterpMatrixKernelR>
 class FInterEngine : public FScalFMMEngine{
 private:
     //Pointer to the kernel to be executed
     InterKernel * kernel;
-
+    MatrixKernelClass * matrix;
     //Link to the tree
-        FOctree<InterCell,ContainerClass,LeafClass> * octree;
+    FOctree<InterCell,ContainerClass,LeafClass> * octree;
 public:
     /**
-     * @brief Constructor : its only build the tree
+     * @brief Constructor : build the tree and the interpolation
+     * kernel
      * @param TreeHeight Height of the tree
      * @param BoxWidth box Width
      * @param BoxCenter double[3] coordinate of the center of the
      * simulation box
      */
-    FInterEngine(int TreeHeight, double BoxWidth , double * BoxCenter) : kernel(nullptr), octree(nullptr){
+    FInterEngine(int TreeHeight, double BoxWidth , double * BoxCenter) : kernel(nullptr), matrix(nullptr), octree(nullptr){
         octree = new FOctree<InterCell,ContainerClass,LeafClass>(TreeHeight,FMath::Min(3,TreeHeight-1),BoxWidth,FPoint(BoxCenter));
+        this->matrix = new MatrixKernelClass();
+        this->kernel = new InterKernel(TreeHeight,BoxWidth,FPoint(BoxCenter),matrix);
+        kernelType = chebyshev;
     }
 
     //TODO free kernel too
     ~FInterEngine(){
         free(octree);
+        free(kernel);
+    }
+
+    //Inserting array of position
+    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;
+    }
+
+    //Inserting arrayS of position
+    void tree_insert_particles(int NbPositions, double * X, double * Y, double * Z){
+        for(int idPart = 0; idPart<NbPositions ; ++idPart){
+            octree->insert(FPoint(X[idPart],Y[idPart],Z[idPart]),idPart);
+        }
+        nbPart += NbPositions;
+    }
+
+    //Set the physical values
+    void set_physical_values(int nbPhysicalValues,double * physicalValues){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    sources->getPhysicalValues()[idxPart] = physicalValues[indexes[idxPart]];
+                }
+            });
+    }
+
+    //Set only a subpart of physical values
+    //Algorithm : loop over each leaf, and then search in user array
+    //if any index matches
+    void set_physical_values_npart( int nbPhysicalValues, int* idxOfParticles, double * physicalValues){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    int iterPart = 0;
+                    bool notFoundYet = true;
+                    while(iterPart < nbPhysicalValues && notFoundYet){
+                        if(indexes[idxPart] == idxOfParticles[iterPart]){
+                            sources->getPhysicalValues()[idxPart] = physicalValues[indexes[idxPart]];
+                            notFoundYet = false;
+                        }
+                        else{
+                            ++iterPart;
+                        }
+                    }
+                }
+            });
+    }
+
+    //get back the physical values
+    void get_physical_values( int nbPhysicalValues, double * physicalValues){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    physicalValues[indexes[idxPart]] = sources->getPhysicalValues()[idxPart];
+                }
+            });
+    }
+
+    //Same algorithm as in set_physical_values_npart
+    void get_physical_values_npart( int nbPhysicalValues, int* idxOfParticles, double * physicalValues){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    int iterPart = 0;
+                    bool notFoundYet = true;
+                    while(iterPart < nbPhysicalValues && notFoundYet){
+                        if(indexes[idxPart] == idxOfParticles[iterPart]){
+                            physicalValues[indexes[idxPart]] = sources->getPhysicalValues()[idxPart];
+                            notFoundYet = false;
+                        }
+                        else{
+                            ++iterPart;
+                        }
+                    }
+                }
+            });
+    }
+
+    void get_forces_xyz( int nbParts, double * forcesToFill){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    forcesToFill[indexes[idxPart]*3+0] = sources->getForcesX()[idxPart];
+                    forcesToFill[indexes[idxPart]*3+1] = sources->getForcesY()[idxPart];
+                    forcesToFill[indexes[idxPart]*3+2] = sources->getForcesZ()[idxPart];
+                }
+            });
+    }
+
+    void get_forces_xyz_npart(int nbParts, int* idxOfParticles , double * forcesToFill){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    int iterPart = 0;
+                    bool notFoundYet = true;
+                    while(iterPart < nbParts && notFoundYet){
+                        if(indexes[idxPart] == idxOfParticles[iterPart]){
+                            forcesToFill[indexes[idxPart]*3+0] = sources->getForcesX()[idxPart];
+                            forcesToFill[indexes[idxPart]*3+1] = sources->getForcesY()[idxPart];
+                            forcesToFill[indexes[idxPart]*3+2] = sources->getForcesZ()[idxPart];
+                            notFoundYet = false;
+                        }
+                        else{
+                            ++iterPart;
+                        }
+                    }
+                }
+            });
+    }
+
+    void get_forces( int nbParts, double * fX, double* fY, double* fZ){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    fX[indexes[idxPart]] = sources->getForcesX()[idxPart];
+                    fY[indexes[idxPart]] = sources->getForcesY()[idxPart];
+                    fZ[indexes[idxPart]] = sources->getForcesZ()[idxPart];
+                }
+            });
     }
+
+    void get_forces_npart(int nbParts, int* idxOfParticles ,double * fX, double* fY, double* fZ){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    int iterPart = 0;
+                    bool notFoundYet = true;
+                    while(iterPart < nbParts && notFoundYet){
+                        if(indexes[idxPart] == idxOfParticles[iterPart]){
+                            fX[indexes[idxPart]] = sources->getForcesX()[idxPart];
+                            fY[indexes[idxPart]] = sources->getForcesY()[idxPart];
+                            fZ[indexes[idxPart]] = sources->getForcesZ()[idxPart];
+                            notFoundYet = false;
+                        }
+                        else{
+                            ++iterPart;
+                        }
+                    }
+                }
+            });
+    }
+
+    //To set initial condition
+    void set_forces_xyz( int nbParts, double * forcesToFill){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    sources->getForcesX()[idxPart] = forcesToFill[indexes[idxPart]*3+0];
+                    sources->getForcesY()[idxPart] = forcesToFill[indexes[idxPart]*3+1];
+                    sources->getForcesZ()[idxPart] = forcesToFill[indexes[idxPart]*3+2];
+                }
+            });
+    }
+    void set_forces_xyz_npart( int nbParts, int* idxOfParticles, double * forcesToFill){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    int iterPart = 0;
+                    bool notFoundYet = true;
+                    while(iterPart < nbParts && notFoundYet){
+                        if(indexes[idxPart] == idxOfParticles[iterPart]){
+                            sources->getForcesX()[idxPart] = forcesToFill[indexes[idxPart]*3+0];
+                            sources->getForcesY()[idxPart] = forcesToFill[indexes[idxPart]*3+1];
+                            sources->getForcesZ()[idxPart] = forcesToFill[indexes[idxPart]*3+2];
+                            notFoundYet = false;
+                        }
+                        else{
+                            ++iterPart;
+                        }
+                    }
+                }
+            });
+    }
+    void set_forces( int nbParts, double * fX, double* fY, double* fZ){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    sources->getForcesX()[idxPart] = fX[indexes[idxPart]];
+                    sources->getForcesY()[idxPart] = fY[indexes[idxPart]];
+                    sources->getForcesZ()[idxPart] = fZ[indexes[idxPart]];
+                }
+            });
+    }
+    void set_forces_npart( int nbParts, int* idxOfParticles, double * fX, double* fY, double* fZ){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    int iterPart = 0;
+                    bool notFoundYet = true;
+                    while(iterPart < nbParts && notFoundYet){
+                        if(indexes[idxPart] == idxOfParticles[iterPart]){
+                            sources->getForcesX()[idxPart] = fX[indexes[idxPart]];
+                            sources->getForcesY()[idxPart] = fY[indexes[idxPart]];
+                            sources->getForcesZ()[idxPart] = fZ[indexes[idxPart]];
+                            notFoundYet = false;
+                        }
+                        else{
+                            ++iterPart;
+                        }
+                    }
+                }
+            });
+    }
+
+    //Set the potentials
+    void set_potentials(int nbPotentials,double * potentialsToRead){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    sources->getPotentials()[idxPart] = potentialsToRead[indexes[idxPart]];
+                }
+            });
+    }
+
+    //Set only a subpart of potentials
+    //Algorithm : loop over each leaf, and then search in user array
+    //if any index matches
+    void set_potentials_npart( int nbPotentials, int* idxOfParticles, double * potentialsToRead){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    int iterPart = 0;
+                    bool notFoundYet = true;
+                    while(iterPart < nbPotentials && notFoundYet){
+                        if(indexes[idxPart] == idxOfParticles[iterPart]){
+                            sources->getPotentials()[idxPart] = potentialsToRead[indexes[idxPart]];
+                            notFoundYet = false;
+                        }
+                        else{
+                            ++iterPart;
+                        }
+                    }
+                }
+            });
+    }
+
+    //get back the potentials
+    void get_potentials( int nbPotentials, double * potentialsToFill){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    potentialsToFill[indexes[idxPart]] = sources->getPotentials()[idxPart];
+                }
+            });
+    }
+
+    //Same algorithm as in set_potentials_npart
+    void get_potentials_npart( int nbPotentials, int* idxOfParticles, double * potentialsToFill){
+        octree->forEachLeaf([&](LeafClass* leaf){
+                ContainerClass * sources = leaf->getSrc();
+                FVector<int> indexes = sources->getIndexes();
+                int nbPartThere = sources->getNbParticles();
+                for(int idxPart = 0 ; idxPart<nbPartThere ; ++idxPart){
+                    int iterPart = 0;
+                    bool notFoundYet = true;
+                    while(iterPart < nbPotentials && notFoundYet){
+                        if(indexes[idxPart] == idxOfParticles[iterPart]){
+                            potentialsToFill[indexes[idxPart]] = sources->getPotentials()[idxPart];
+                            notFoundYet = false;
+                        }
+                        else{
+                            ++iterPart;
+                        }
+                    }
+                }
+            });
+    }
+
+    // class ContainerClass = FP2PParticleContainerIndexed<>,
+    //     class LeafClass = FSimpleLeaf<FP2PParticleContainerIndexed<> >,
+    //     class MatrixKernelClass = FInterpMatrixKernelR>
+
+
+    void execute_fmm(){
+        typedef FOctree<InterCell,ContainerClass,LeafClass> OctreeClass;
+        switch(Algorithm){
+        case 0:
+            {
+                typedef FFmmAlgorithm<OctreeClass,InterCell,ContainerClass,InterKernel,LeafClass> AlgoClassSeq;
+                AlgoClassSeq algoSeq(octree,kernel);
+                algoSeq.execute();
+                break;
+            }
+        case 1:
+            {
+                typedef FFmmAlgorithmThread<OctreeClass,InterCell,ContainerClass,InterKernel,LeafClass> AlgoClassThread;
+                AlgoClassThread algoThread(octree,kernel);
+                algoThread.execute();
+                break;
+            }
+        default :
+            std::cout<< "No algorithm found (probably for strange reasons) : "<< Algorithm <<" exiting" << std::endl;
+        }
+    }
+
+
 };
 
 
diff --git a/Addons/CKernelApi/Src/FScalFMMEngine.hpp b/Addons/CKernelApi/Src/FScalFMMEngine.hpp
index 6942c02c6..f1a4d940e 100644
--- a/Addons/CKernelApi/Src/FScalFMMEngine.hpp
+++ b/Addons/CKernelApi/Src/FScalFMMEngine.hpp
@@ -47,17 +47,39 @@
  * @class FScalFMMEngine
  */
 class FScalFMMEngine{
-private:
-    scalfmm_kernel_type kernel;
+protected:
+    scalfmm_kernel_type kernelType;
+    scalfmm_out_of_box_behavior OutOfBoxBehavior;
+    scalfmm_algorithm Algorithm;
     FVector<bool> progress;
+    int nbPart;
 
 public:
+    FScalFMMEngine() : OutOfBoxBehavior(exiting), 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
+    //kernel
     scalfmm_kernel_type getKernelType(){
-        return this->kernel;
+        return this->kernelType;
+    }
+
+    //To deal with particles moving outside the box
+    void out_of_the_box_config(scalfmm_out_of_box_behavior config){
+        this->OutOfBoxBehavior = config;
     }
 
-    //Function about the tree (to be redefined)
+    //To change default algorithm
+    void algorithm_config(scalfmm_algorithm config){
+        this->Algorithm = config;
+    }
+
+
+    //Functions displayed there are function that are to be redefined
+    //by specific Engine
 
+    //Function about the tree
     virtual void tree_insert_particles( int NbPositions, double * arrayX, double * arrayY, double * arrayZ){
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
@@ -96,6 +118,7 @@ public:
     virtual void get_forces_npart( int nbParts, int* idxOfParticles, double * fX, double* fY, double* fZ){
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
+
     //To set initial condition
     virtual void set_forces_xyz( int nbParts, double * forcesToFill){
         FAssertLF(0,"No tree instancied, exiting ...\n");
@@ -113,17 +136,17 @@ public:
     virtual void get_potentials( int nbParts, double * potentialsToFill){
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
-    virtual void set_potentials( int nbParts, double * potentialsToFill){
+    virtual void set_potentials( int nbParts, double * potentialsToRead){
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
     virtual void get_potentials_npart( int nbParts, int* idxOfParticles, double * potentialsToFill){
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
-    virtual void set_potentials_npart( int nbParts, int* idxOfParticles, double * potentialsToFill){
+    virtual void set_potentials_npart( int nbParts, int* idxOfParticles, double * potentialsToRead){
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
 
-    //To deal with positions
+    //Function to move particles
     virtual void add_to_positions_xyz( int NbPositions, double * updatedXYZ){
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
@@ -134,7 +157,7 @@ public:
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
     virtual void add_to_positions_npart( int NbPositions, int* idxOfParticles,
-                                             double * X, double * Y , double * Z){
+                                         double * X, double * Y , double * Z){
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
     virtual void set_positions_xyz( int NbPositions, double * updatedXYZ){
@@ -147,7 +170,7 @@ public:
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
     virtual void set_positions_npart( int NbPositions, int* idxOfParticles,
-                                          double * X, double * Y , double * Z){
+                                      double * X, double * Y , double * Z){
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
     virtual void get_positions_xyz( int NbPositions, double * updatedXYZ){
@@ -160,7 +183,7 @@ public:
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
     virtual void get_positions_npart( int NbPositions, int* idxOfParticles,
-                                          double * X, double * Y , double * Z){
+                                      double * X, double * Y , double * Z){
         FAssertLF(0,"No tree instancied, exiting ...\n");
     }
 
@@ -170,8 +193,8 @@ public:
         FAssertLF(0,"No user kernel defined, exiting ...\n");
     }
 
-    virtual void scalfmm_execute_fmm(){
-        FAssertLF(0,"No kernel set, exiting ...\n");
+    virtual void execute_fmm(){
+        FAssertLF(0,"No kernel set, cannot execute anything, exiting ...\n");
     }
 
 };
@@ -272,6 +295,11 @@ extern "C" void scalfmm_set_potentials_npart(scalfmm_handle Handle, int nbParts,
 
 
 //To deal with positions
+//Out of the box behavior
+extern "C" void scalfmm_out_of_the_box_config(scalfmm_handle Handle,scalfmm_out_of_box_behavior config){
+    ((ScalFmmCoreHandle * ) Handle)->engine->out_of_the_box_config(config);
+}
+
 //Update
 extern "C" void scalfmm_add_to_positions_xyz(scalfmm_handle Handle, int NbPositions, double * updatedXYZ){
     ((ScalFmmCoreHandle * ) Handle)->engine->add_to_positions_xyz(NbPositions, updatedXYZ);
@@ -286,7 +314,7 @@ extern "C" void scalfmm_add_to_positions_xyz_npart(scalfmm_handle Handle, int Nb
 }
 
 extern "C" void scalfmm_add_to_positions_npart(scalfmm_handle Handle, int NbPositions, int* idxOfParticles,
-                                                   double * X, double * Y , double * Z){
+                                               double * X, double * Y , double * Z){
     ((ScalFmmCoreHandle * ) Handle)->engine->add_to_positions_npart(NbPositions, idxOfParticles, X, Y, Z);
 }
 //Set new positions
@@ -320,14 +348,20 @@ extern "C" void scalfmm_get_positions_xyz_npart(scalfmm_handle Handle, int NbPos
 }
 
 extern "C" void scalfmm_get_positions_npart(scalfmm_handle Handle, int NbPositions, int* idxOfParticles,
-                                                double * X, double * Y , double * Z){
+                                            double * X, double * Y , double * Z){
     ((ScalFmmCoreHandle * ) Handle)->engine->get_positions_npart(NbPositions, idxOfParticles, X, Y, Z);
 }
 
+//To choose algorithm
+extern "C" void scalfmm_algorithm_config(scalfmm_handle Handle, scalfmm_algorithm config){
+    ((ScalFmmCoreHandle * ) Handle)->engine->algorithm_config(config);
+}
+
 //Executing FMM
 extern "C" void scalfmm_execute_fmm(scalfmm_handle Handle){
-    ((ScalFmmCoreHandle * ) Handle)->engine->scalfmm_execute_fmm();
+    ((ScalFmmCoreHandle * ) Handle)->engine->execute_fmm();
 }
 
 
+
 #endif
-- 
GitLab