Commit 7a215591 authored by BRAMAS Berenger's avatar BRAMAS Berenger

Add the wrappers to work with adaptive kernel (it works but has not been tested a lot)

parent 3ca1f760
#ifndef FABSTRACTADAPTATIVEKERNEL
#define FABSTRACTADAPTATIVEKERNEL
/**
* This class represent the method that an adaptative kernel must implement.
* There are two kinds of operators, the first one represent computation and the others
* should return the cretiria to know when the P2M should be performed.
*/
template <class CellClass, class ContainerClass>
class FAbstractAdaptativeKernel {
public:
virtual ~FAbstractAdaptativeKernel(){
}
virtual void P2M(CellClass* const pole, const int cellLevel, const ContainerClass* const particles) = 0;
virtual void M2M(CellClass* const pole, const int poleLevel, const CellClass* const subCell, const int subCellLevel) = 0;
virtual void P2L(CellClass* const local, const int localLevel, const ContainerClass* const particles) = 0;
virtual void M2L(CellClass* const local, const int localLevel, const CellClass* const aNeighbor, const int neighborLevel) = 0;
virtual void M2P(const CellClass* const pole, const int poleLevel, ContainerClass* const particles) = 0;
virtual void L2L(const CellClass* const local, const int localLevel, CellClass* const subCell, const int subCellLevel) = 0;
virtual void L2P(const CellClass* const local, const int cellLevel, ContainerClass* const particles) = 0;
virtual void P2P(ContainerClass* target, const ContainerClass* sources) = 0;
virtual bool preferP2M(const ContainerClass* const particles) = 0;
virtual bool preferP2M(const int atLevel, const ContainerClass*const particles[], const int nbContainers) = 0;
};
#endif
#ifndef FADAPTATIVECELL
#define FADAPTATIVECELL
#include "../Components/FBasicCell.hpp"
#include "../Containers/FVector.hpp"
/**
* This class is a wrapper to work with adaptative kernel
* It contains a pointer to the real computation cell but use it only if
* the cell is adaptative AND has been use for development.
*
* A cell is adaptative if:
* × it has more than one child
* × it used for development
* × it is usde to store the leaves
* Else it stores a pointer to the lower adaptive cell.
*/
template <class RealCell, class ContainerClass>
class FAdaptativeCell : public FBasicCell {
/** The cell used for the computation */
RealCell* realCell;
/** To keep track of the cell state */
bool IamAdaptative;
/** If not adaptative then we need to know the lower adaptative cell */
FAdaptativeCell<RealCell, ContainerClass>* subAdaptativeCell;
/** The lower adaptative cell level */
int subAdaptativeLevel;
/** The leaves that have been skiped for the P2M/M2M... */
FVector<ContainerClass*> subLeaves;
public:
/** Set has not adaptative by default */
FAdaptativeCell() : realCell(nullptr), IamAdaptative(false), subAdaptativeCell(nullptr), subAdaptativeLevel(0){
}
~FAdaptativeCell(){
delete realCell;
}
void resetToInitialState(){
subLeaves.clear();
if(realCell){
realCell->resetToInitialState();
}
}
////////////////////////////////////////////////////////////////////////////////
/// Get the real cell
////////////////////////////////////////////////////////////////////////////////
/** To say if it is used for development or not */
void setHaveDevelopment(const bool inHaveDevelopment) {
if(inHaveDevelopment && !realCell){
// alloc and init the real cell
realCell = new RealCell;
realCell->setMortonIndex(this->getMortonIndex());
realCell->setCoordinate(this->getCoordinate());
// clean other information
subAdaptativeCell = nullptr;
subAdaptativeLevel = 0;
subLeaves.clear();
}
else if(!inHaveDevelopment && realCell){
// clean real cell if needed
delete realCell;
realCell = nullptr;
}
}
bool hasDevelopment() const{
return realCell != nullptr;
}
RealCell* getRealCell(){
return realCell;
}
const RealCell* getRealCell() const {
return realCell;
}
////////////////////////////////////////////////////////////////////////////////
/// Set adaptative
////////////////////////////////////////////////////////////////////////////////
bool isAdaptative() const {
return IamAdaptative;
}
void setAdaptative(const bool inIsAdaptative) {
IamAdaptative = inIsAdaptative;
}
////////////////////////////////////////////////////////////////////////////////
/// Manage the sub leaves
////////////////////////////////////////////////////////////////////////////////
void addSubLeaf(const ContainerClass* aLeaf){
subLeaves.push(const_cast<ContainerClass*>(aLeaf));
}
void addSubLeaf(ContainerClass* aLeaf){
subLeaves.push(aLeaf);
}
void addSubLeaves(const ContainerClass*const* aLeavesToInsert, const int nbLeavesToInsert){
subLeaves.memocopy(const_cast<ContainerClass*const*>(aLeavesToInsert),nbLeavesToInsert);
}
int getNbSubLeaves() const {
return subLeaves.getSize();
}
ContainerClass* const * getSubLeaves() {
return subLeaves.data();
}
const ContainerClass * const * getSubLeaves() const{
return subLeaves.data();
}
ContainerClass* getSubLeaf(const int leafIdx) const{
return subLeaves[leafIdx];
}
////////////////////////////////////////////////////////////////////////////////
/// Manage the sub cell
////////////////////////////////////////////////////////////////////////////////
void setSubAdaptativeCell(FAdaptativeCell<RealCell,ContainerClass>* inSubAdaptativeCell, const int inSubAdaptativeLevel){
subAdaptativeCell = inSubAdaptativeCell;
subAdaptativeLevel = inSubAdaptativeLevel;
}
void setSubAdaptativeCell(const FAdaptativeCell<RealCell,ContainerClass>* inSubAdaptativeCell, const int inSubAdaptativeLevel){
subAdaptativeCell = const_cast<FAdaptativeCell<RealCell,ContainerClass>*>(inSubAdaptativeCell);
subAdaptativeLevel = inSubAdaptativeLevel;
}
FAdaptativeCell<RealCell,ContainerClass>* getSubAdaptativeCell() {
return subAdaptativeCell;
}
FAdaptativeCell<RealCell,ContainerClass>* getSubAdaptativeCell() const {
return subAdaptativeCell;
}
int getSubAdaptativeLevel() const {
return subAdaptativeLevel;
}
};
#endif
This diff is collapsed.
// ===================================================================================
// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// 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".
// ===================================================================================
#include <iostream>
#include <cstdio>
#include "../../Src/Utils/FParameters.hpp"
#include "../../Src/Utils/FTic.hpp"
#include "../../Src/Containers/FOctree.hpp"
#include "../../Src/Containers/FVector.hpp"
#include "../../Src/Components/FSimpleLeaf.hpp"
#include "../../Src/Utils/FPoint.hpp"
#include "../../Src/Components/FTestParticleContainer.hpp"
#include "../../Src/Components/FTestCell.hpp"
#include "../../Src/Components/FTestKernels.hpp"
#include "../../Src/Core/FFmmAlgorithm.hpp"
#include "../../Src/Core/FFmmAlgorithmThread.hpp"
#include "../../Src/Core/FFmmAlgorithmTask.hpp"
#include "../../Src/Components/FBasicKernels.hpp"
#include "../../Src/Files/FRandomLoader.hpp"
#include "../../Src/Adaptative/FAdaptativeCell.hpp"
#include "../../Src/Adaptative/FAdaptativeKernelWrapper.hpp"
#include "../../Src/Adaptative/FAbstractAdaptativeKernel.hpp"
template< class CellClass, class ContainerClass>
class FAdaptiveTestKernel : public FTestKernels<CellClass, ContainerClass>, public FAbstractAdaptativeKernel<CellClass, ContainerClass> {
public:
using FTestKernels<CellClass, ContainerClass>::P2M;
using FTestKernels<CellClass, ContainerClass>::M2M;
using FTestKernels<CellClass, ContainerClass>::M2L;
using FTestKernels<CellClass, ContainerClass>::L2L;
using FTestKernels<CellClass, ContainerClass>::L2P;
using FTestKernels<CellClass, ContainerClass>::P2P;
void P2M(CellClass* const pole, const int /*cellLevel*/, const ContainerClass* const particles) override {
pole->setDataUp(pole->getDataUp() + particles->getNbParticles());
}
void M2M(CellClass* const pole, const int /*poleLevel*/, const CellClass* const subCell, const int /*subCellLevel*/) override {
pole->setDataUp(pole->getDataUp() + subCell->getDataUp());
}
void P2L(CellClass* const local, const int /*localLevel*/, const ContainerClass* const particles) override {
local->setDataDown(local->getDataDown() + particles->getNbParticles());
}
void M2L(CellClass* const local, const int /*localLevel*/, const CellClass* const aNeighbor, const int /*neighborLevel*/) override {
local->setDataDown(local->getDataDown() + aNeighbor->getDataUp());
}
void M2P(const CellClass* const pole, const int /*poleLevel*/, ContainerClass* const particles) override {
long long int*const particlesAttributes = particles->getDataDown();
for(int idxPart = 0 ; idxPart < particles->getNbParticles() ; ++idxPart){
particlesAttributes[idxPart] += pole->getDataUp();
}
}
void L2L(const CellClass* const local, const int /*localLevel*/, CellClass* const subCell, const int /*subCellLevel*/) override {
subCell->setDataDown(local->getDataDown() + subCell->getDataDown());
}
void L2P(const CellClass* const local, const int /*cellLevel*/, ContainerClass* const particles) override {
long long int*const particlesAttributes = particles->getDataDown();
for(int idxPart = 0 ; idxPart < particles->getNbParticles() ; ++idxPart){
particlesAttributes[idxPart] += local->getDataDown();
}
}
void P2P(ContainerClass* target, const ContainerClass* sources) override {
long long int*const particlesAttributes = target->getDataDown();
for(int idxPart = 0 ; idxPart < target->getNbParticles() ; ++idxPart){
particlesAttributes[idxPart] += sources->getNbParticles();
}
}
bool preferP2M(const ContainerClass* const particles) override {
return particles->getNbParticles() < 10;
}
bool preferP2M(const int /*atLevel*/, const ContainerClass*const particles[], const int nbContainers) override {
int counterParticles = 0;
for(int idxContainer = 0 ; idxContainer < nbContainers ; ++idxContainer){
counterParticles += particles[idxContainer]->getNbParticles();
}
return counterParticles < 10;
}
};
/** This program show an example of use of the fmm basic algo
* it also check that each particles is impacted each other particles
*/
// Simply create particles and try the kernels
int main(int argc, char ** argv){
typedef FTestCell CellClass;
typedef FTestParticleContainer ContainerClass;
typedef FSimpleLeaf< ContainerClass > LeafClass;
typedef FAdaptiveTestKernel< CellClass, ContainerClass > KernelClass;
typedef FAdaptativeCell< CellClass, ContainerClass > CellWrapperClass;
typedef FAdaptativeKernelWrapper< KernelClass, CellClass, ContainerClass > KernelWrapperClass;
typedef FOctree< CellWrapperClass, ContainerClass , LeafClass > OctreeClass;
// FFmmAlgorithmTask FFmmAlgorithmThread
typedef FFmmAlgorithm<OctreeClass, CellWrapperClass, ContainerClass, KernelWrapperClass, LeafClass > FmmClass;
///////////////////////What we do/////////////////////////////
std::cout << ">> This executable has to be used to test the FMM algorithm.\n";
//////////////////////////////////////////////////////////////
const int NbLevels = FParameters::getValue(argc,argv,"-h", 7);
const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3);
const int NbPart = FParameters::getValue(argc,argv,"-nb", 2000000);
FTic counter;
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
FRandomLoader loader(NbPart, 1, FPoint(0.5,0.5,0.5), 1);
OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox());
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
std::cout << "Creating & Inserting " << NbPart << " particles ..." << std::endl;
std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl;
counter.tic();
{
FPoint particlePosition;
for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
loader.fillParticle(&particlePosition);
tree.insert(particlePosition);
}
}
counter.tac();
std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl;
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
std::cout << "Working on particles ..." << std::endl;
counter.tic();
KernelWrapperClass kernels; // FTestKernels FBasicKernels
FmmClass algo(&tree,&kernels); //FFmmAlgorithm FFmmAlgorithmThread
algo.execute();
counter.tac();
std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl;
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
tree.forEachCellLeaf([&](CellWrapperClass*, LeafClass* leaf){
long long int*const particlesAttributes = leaf->getTargets()->getDataDown();
for(int idxPart = 0 ; idxPart < leaf->getTargets()->getNbParticles() ; ++idxPart){
if(particlesAttributes[idxPart] != (NbPart-1)){
printf("Incorrect %lld instead of %d\n", particlesAttributes[idxPart], (NbPart-1));
}
}
});
return 0;
}
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