// =================================================================================== // 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 Interpolations kernels. */ #ifndef FINTERENGINE_HPP #define FINTERENGINE_HPP #include "FScalFMMEngine.hpp" #include "Kernels/Interpolation/FInterpMatrixKernel.hpp" #include "Components/FTypedLeaf.hpp" #include "Arranger/FOctreeArranger.hpp" #include "Arranger/FArrangerPeriodic.hpp" #include "Arranger/FBasicParticleContainerIndexedMover.hpp" #include "Arranger/FParticleTypedIndexedMover.hpp" #include "Extensions/FExtendCellType.hpp" #include "Core/FFmmAlgorithmThread.hpp" #include "Core/FFmmAlgorithmSectionTask.hpp" #include "Core/FFmmAlgorithmTask.hpp" #include "Core/FFmmAlgorithm.hpp" #include "Core/FFmmAlgorithmPeriodic.hpp" #include "Core/FFmmAlgorithmThreadTsm.hpp" /** * @class FInterEngine implements API for Interpolations kernels, its * templates can be ChebCell/ChebKernel or UnifCell/UnifKernel */ template > class FInterEngine : public FScalFMMEngine{ private: //Typedefs typedef FP2PParticleContainerIndexed ContainerClass; typedef FTypedLeaf LeafClassTyped; //Typedef on the Typed OctreeClass typedef FOctree OctreeClass; //Pointer to the kernel to be executed InterKernel * kernel; MatrixKernelClass * matrix; //Link to the tree OctreeClass * octree; // ArrangerClass * arranger; public: /** * @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(scalfmm_kernel_type KernelType, scalfmm_algorithm algo) : kernel(nullptr), matrix(nullptr), octree(nullptr)/*,arranger(nullptr)*/{ FScalFMMEngine::kernelType = KernelType; FScalFMMEngine::Algorithm = algo; } void build_tree(int TreeHeight, FReal BoxWidth , FReal * BoxCenter,User_Scalfmm_Cell_Descriptor notUsedHere){ 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); } //TODO free kernel too ~FInterEngine(){ delete matrix; if(octree){ delete octree; } if(kernel){ delete kernel; } // if(arranger){ // delete arranger; // } } //Inserting array of position //Need to be disabled if Source/Target is used void tree_insert_particles_xyz(int NbPositions, FReal * XYZ, PartType type){ if(type == BOTH){ for(FSize idPart = 0; idPartinsert(FPoint(&XYZ[3*idPart]),idPart); } FScalFMMEngine::nbPart += NbPositions; }else{ if(type==SOURCE){ for(FSize idPart = 0; idPartinsert(FPoint(&XYZ[3*idPart]),FParticleTypeSource,idPart); } FScalFMMEngine::nbPart += NbPositions; }else{ for(FSize idPart = 0; idPartinsert(FPoint(&XYZ[3*idPart]),FParticleTypeTarget,idPart); } FScalFMMEngine::nbPart += NbPositions; } } } //Inserting arrayS of position //Need to be disabled if Source/Target is used void tree_insert_particles(int NbPositions, FReal * X, FReal * Y, FReal * Z, PartType type){ if(type == BOTH){ for(FSize idPart = 0; idPartinsert(FPoint(X[idPart],Y[idPart],Z[idPart]),idPart); } FScalFMMEngine::nbPart += NbPositions; }else{ if(type==SOURCE){ for(FSize idPart = 0; idPartinsert(FPoint(X[idPart],Y[idPart],Z[idPart]),FParticleTypeSource,idPart); } FScalFMMEngine::nbPart += NbPositions; }else{ for(FSize idPart = 0; idPartinsert(FPoint(X[idPart],Y[idPart],Z[idPart]),FParticleTypeTarget,idPart); } FScalFMMEngine::nbPart += NbPositions; } } } // void tree_abstract_insert(int NbPartToInsert, int nbAttributeToInsert, int * strideForEachAtt, // FReal* rawDatas){ // FAssertLF(nbAttributeToInsert > 2,"Need space to store positions, thus nbAttributeToInsert must be >= 3\nExiting ... \n"); // FAssertLF(nbAttributeToInsert < 15,"Cannot instanciate more than 15 Attribute per Particules\n"); // FRunIf::Run(nbAttributeToInsert,); // generic_tree_abstract_insert(octree, // NbPartToInsert,strideForEachAtt,rawDatas); // } //Set the physical values void set_physical_values(int nbPhysicalValues,FReal * physicalValues, PartType type){ int checkCount = 0; if(type == SOURCE){ octree->forEachLeaf([&] (LeafClass * leaf){ ContainerClass * sources = leaf->getSrc(); const FVector& indexes = sources->getIndexes(); FSize nbPartThere = sources->getNbParticles(); for(int idx=0 ; idxgetPhysicalValues()[idx] = physicalValues[indexes[idx]]; ++checkCount; } }); } else{ // type must be equal to TARGETS or BOTH octree->forEachLeaf([&] (LeafClass * leaf){ ContainerClass * targets = leaf->getTargets(); const FVector& indexes = targets->getIndexes(); FSize nbPartThere = targets->getNbParticles(); for(int idx=0 ; idxgetPhysicalValues()[idx] = physicalValues[indexes[idx]]; ++checkCount; } }); } if(checkCount < nbPhysicalValues){std::cout << "Not all "< nbPhysicalValues){std::cout << "More parts than "<forEachLeaf([&](LeafClass* leaf){ ContainerClass * sources = leaf->getSrc(); const FVector& indexes = sources->getIndexes(); FSize nbPartThere = sources->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetPhysicalValues()[idxPart] = physicalValues[iterPart]; checkCount++; notFoundYet = false; } else{ ++iterPart; } } } }); }else{//Parts are target octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * targets = leaf->getTargets(); const FVector& indexes = targets->getIndexes(); FSize nbPartTarget = targets->getNbParticles(); //Targets part for(FSize idxPart = 0 ; idxPartgetPhysicalValues()[idxPart] = physicalValues[iterPart]; notFoundYet = false; checkCount++; } else{ ++iterPart; } } } }); } if(checkCount < nbPhysicalValues){std::cout << "Not all "< nbPhysicalValues){std::cout << "More parts than "<forEachLeaf([&](LeafClass* leaf){ ContainerClass * sources = leaf->getSrc(); const FVector& indexes = sources->getIndexes(); FSize nbPartThere = sources->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetPhysicalValues()[idxPart]; checkCount++; } }); } else{//Get the targets forces octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * targets = leaf->getTargets(); const FVector& indexes = targets->getIndexes(); FSize nbPartThere = targets->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetPhysicalValues()[idxPart]; checkCount++; } }); } if(checkCount < nbPhysicalValues){std::cout << "Not all "< nbPhysicalValues){std::cout << "More parts than "<forEachLeaf([&](LeafClass* leaf){ ContainerClass * sources = leaf->getSrc(); const FVector& indexes = sources->getIndexes(); FSize nbPartThere = sources->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetPhysicalValues()[idxPart]; notFoundYet = false; checkCount++; } else{ ++iterPart; } } } }); }else{ //Target octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * targets = leaf->getTargets(); const FVector& indexes = targets->getIndexes(); FSize nbPartThere = targets->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetPhysicalValues()[idxPart]; notFoundYet = false; checkCount++; } else{ ++iterPart; } } } }); } if(checkCount < nbPhysicalValues){std::cout << "Not all "< nbPhysicalValues){std::cout << "More parts than "<::template generic_get_forces_xyz(octree,nbParts,forcesToFill,type); } void get_forces(int nbParts, FReal * fX, FReal* fY, FReal* fZ, PartType type){ FScalFMMEngine::template generic_get_forces(octree,nbParts,fX,fY,fZ,type); } void get_forces_nbpart(int nbParts, int* idxOfParticles ,FReal * fX, FReal* fY, FReal* fZ, PartType type){ FScalFMMEngine::template generic_get_forces_xyz_npart(octree,nbParts,idxOfParticles,fX,fY,fZ,type); } void get_forces_xyz_nbpart(int nbParts, int* idxOfParticles, FReal * forcesToFill, PartType type){ FScalFMMEngine::template generic_get_forces_xyz_npart(octree,nbParts,idxOfParticles,forcesToFill,type); } //To set initial condition void set_forces_xyz( int nbParts, FReal * forcesToRead, PartType type){ int checkCount = 0; if(type == SOURCE || type==BOTH){ octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * sources = leaf->getSrc(); const FVector& indexes = sources->getIndexes(); FSize nbPartThere = sources->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetForcesX()[idxPart] = forcesToRead[indexes[idxPart]*3+0]; sources->getForcesY()[idxPart] = forcesToRead[indexes[idxPart]*3+1]; sources->getForcesZ()[idxPart] = forcesToRead[indexes[idxPart]*3+2]; checkCount++; } }); } else{//Set force on target octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * targets = leaf->getTargets(); const FVector& indexes = targets->getIndexes(); FSize nbPartThere = targets->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetForcesX()[idxPart] = forcesToRead[indexes[idxPart]*3+0]; targets->getForcesY()[idxPart] = forcesToRead[indexes[idxPart]*3+1]; targets->getForcesZ()[idxPart] = forcesToRead[indexes[idxPart]*3+2]; checkCount++; } }); } if(checkCount < nbParts){std::cout << "Not all "< nbParts){std::cout << "More parts than "<forEachLeaf([&](LeafClass* leaf){ ContainerClass * sources = leaf->getSrc(); const FVector& indexes = sources->getIndexes(); FSize nbPartThere = sources->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetForcesX()[idxPart] = forcesToRead[iterPart]; sources->getForcesY()[idxPart] = forcesToRead[iterPart]; sources->getForcesZ()[idxPart] = forcesToRead[iterPart]; notFoundYet = false; checkCount++; } else{ ++iterPart; } } } }); }else{ //Targets octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * targets = leaf->getTargets(); const FVector& indexes = targets->getIndexes(); FSize nbPartThere = targets->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetForcesX()[idxPart] = forcesToRead[iterPart]; targets->getForcesY()[idxPart] = forcesToRead[iterPart]; targets->getForcesZ()[idxPart] = forcesToRead[iterPart]; notFoundYet = false; checkCount++; } else{ ++iterPart; } } } }); } if(checkCount < nbParts){std::cout << "Not all "< nbParts){std::cout << "More parts than "<forEachLeaf([&](LeafClass* leaf){ ContainerClass * sources = leaf->getSrc(); const FVector& indexes = sources->getIndexes(); FSize nbPartThere = sources->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetForcesX()[idxPart] = fX[indexes[idxPart]]; sources->getForcesY()[idxPart] = fY[indexes[idxPart]]; sources->getForcesZ()[idxPart] = fZ[indexes[idxPart]]; checkCount++; } }); }else{//Targets octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * targets = leaf->getTargets(); const FVector& indexes = targets->getIndexes(); FSize nbPartThere = targets->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetForcesX()[idxPart] = fX[indexes[idxPart]]; targets->getForcesY()[idxPart] = fY[indexes[idxPart]]; targets->getForcesZ()[idxPart] = fZ[indexes[idxPart]]; checkCount++; } }); } if(checkCount < nbParts){std::cout << "Not all "< nbParts){std::cout << "More parts than "<forEachLeaf([&](LeafClass* leaf){ ContainerClass * sources = leaf->getSrc(); const FVector& indexes = sources->getIndexes(); FSize nbPartThere = sources->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetForcesX()[idxPart] = fX[indexes[idxPart]]; sources->getForcesY()[idxPart] = fY[indexes[idxPart]]; sources->getForcesZ()[idxPart] = fZ[indexes[idxPart]]; notFoundYet = false; checkCount++; } else{ ++iterPart; } } } }); }else{//Targets octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * targets = leaf->getTargets(); const FVector& indexes = targets->getIndexes(); FSize nbPartThere = targets->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetForcesX()[idxPart] = fX[indexes[idxPart]]; targets->getForcesY()[idxPart] = fY[indexes[idxPart]]; targets->getForcesZ()[idxPart] = fZ[indexes[idxPart]]; notFoundYet = false; checkCount++; } else{ ++iterPart; } } } }); } if(checkCount < nbParts){std::cout << "Not all "< nbParts){std::cout << "More parts than "<::template generic_get_positions_xyz(octree,NbPositions,positionsToFill,type); } void get_positions_xyz_npart(int NbPositions, int * idxOfParticles, double * positionsToFill,PartType type){ FScalFMMEngine::template generic_get_positions_xyz_npart(octree,NbPositions,idxOfParticles,positionsToFill,type); } void get_positions( int NbPositions, double *X, double *Y , double *Z, PartType type){ FScalFMMEngine::template generic_get_positions(octree,NbPositions,X,Y,Z,type); } void get_positions_npart(int NbPositions, int * idxOfParticles,double * X, double * Y , double * Z,PartType type){ FScalFMMEngine::template generic_get_positions_npart(octree,NbPositions,idxOfParticles,X,Y,Z,type); } void set_positions_xyz(int NbPositions, FReal * updatedXYZ, PartType type){ FScalFMMEngine::template generic_set_positions_xyz(octree,NbPositions,updatedXYZ,type); } void set_positions(int NbPositions, FReal * X, FReal * Y, FReal * Z, PartType type){ FScalFMMEngine::template generic_set_positions(octree,NbPositions,X,Y,Z,type); } void set_positions_xyz_npart(int NbPositions, int* idxOfParticles, FReal * updatedXYZ, PartType type){ FScalFMMEngine::template generic_set_positions_xyz_npart(octree,NbPositions,idxOfParticles,updatedXYZ,type); } void set_positions_npart(int NbPositions, int* idxOfParticles, FReal * X, FReal * Y , FReal * Z, PartType type){ FScalFMMEngine::template generic_set_positions_npart(octree,NbPositions,idxOfParticles,X,Y,Z,type); } void add_to_positions_xyz(int NbPositions,FReal * updatedXYZ,PartType type){ FScalFMMEngine::template generic_add_to_positions_xyz(octree,NbPositions,updatedXYZ,type); } void add_to_positions(int NbPositions,FReal * X, FReal * Y , FReal * Z, PartType type){ FScalFMMEngine::template generic_add_to_positions(octree,NbPositions,X,Y,Z,type); } //Set the potentials void set_potentials(int nbPotentials,FReal * potentialsToRead, PartType type){ int checkCount = 0; if(type == SOURCE || type==BOTH){ octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * sources = leaf->getSrc(); const FVector& indexes = sources->getIndexes(); FSize nbPartThere = sources->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetPotentials()[idxPart] = potentialsToRead[indexes[idxPart]]; checkCount++; } }); }else{//Targets octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * targets = leaf->getTargets(); const FVector& indexes = targets->getIndexes(); FSize nbPartThere = targets->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetPotentials()[idxPart] = potentialsToRead[indexes[idxPart]]; checkCount++; } }); } if(checkCount < nbPotentials){std::cout << "Not all "< nbPotentials){std::cout << "More parts than "<forEachLeaf([&](LeafClass* leaf){ ContainerClass * sources = leaf->getSrc(); const FVector& indexes = sources->getIndexes(); FSize nbPartThere = sources->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetPotentials()[idxPart] = potentialsToRead[iterPart]; notFoundYet = false; checkCount++; } else{ ++iterPart; } } } }); }else{//Targets octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * targets = leaf->getTargets(); const FVector& indexes = targets->getIndexes(); FSize nbPartThere = targets->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetPotentials()[idxPart] = potentialsToRead[iterPart]; notFoundYet = false; checkCount++; } else{ ++iterPart; } } } }); } if(checkCount < nbPotentials){std::cout << "Not all "< nbPotentials){std::cout << "More parts than "<forEachLeaf([&](LeafClass* leaf){ ContainerClass * sources = leaf->getSrc(); FSize nbPartThere = sources->getNbParticles(); const FVector& indexes = sources->getIndexes(); for(FSize idxPart = 0 ; idxPartgetPotentials()[idxPart]; checkCount++; } }); }else{//Targets octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * targets = leaf->getTargets(); const FVector& indexes = targets->getIndexes(); FSize nbPartThere = targets->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetPotentials()[idxPart]; checkCount++; } }); } if(checkCount < nbPotentials){std::cout << "Not all "< nbPotentials){std::cout << "More parts than "<forEachLeaf([&](LeafClass* leaf){ ContainerClass * sources = leaf->getSrc(); const FVector& indexes = sources->getIndexes(); FSize nbPartThere = sources->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetPotentials()[idxPart]; notFoundYet = false; checkCount++; } else{ ++iterPart; } } } }); }else{ octree->forEachLeaf([&](LeafClass* leaf){ ContainerClass * targets = leaf->getTargets(); const FVector& indexes = targets->getIndexes(); FSize nbPartThere = targets->getNbParticles(); for(FSize idxPart = 0 ; idxPartgetPotentials()[idxPart]; notFoundYet = false; checkCount++; } else{ ++iterPart; } } } }); } if(checkCount < nbPotentials){std::cout << "Not all "< nbPotentials){std::cout << "More parts than "<::template generic_apply_on_cell(octree); } // void update_tree(){ // if(arranger){ // arranger->rearrange(); // } // else{ // if(FScalFMMEngine::Algorithm == 2){ //case in wich the periodic algorithm is used // arranger = new ArrangerClassPeriodic(octree); // arranger->rearrange(); // } // else{ // arranger = new ArrangerClass(octree); // arranger->rearrange(); // } // } // } void execute_fmm(){ switch(FScalFMMEngine::Algorithm){ case 0: { typedef FFmmAlgorithm AlgoClassSeq; AlgoClassSeq* algoSeq = new AlgoClassSeq(octree,kernel); algoSeq->execute(); FScalFMMEngine::algoTimer = algoSeq; FScalFMMEngine::abstrct = algoSeq; break; } case 1: { typedef FFmmAlgorithmThread AlgoClassThread; AlgoClassThread* algoThread = new AlgoClassThread(octree,kernel); algoThread->execute(); FScalFMMEngine::algoTimer = algoThread; FScalFMMEngine::abstrct = algoThread; break; } case 2: { typedef FFmmAlgorithmPeriodic AlgoClassPeriodic; AlgoClassPeriodic algoPeriod(octree,2); algoPeriod.setKernel(kernel); algoPeriod.execute(); break; } case 3: { typedef FFmmAlgorithmThreadTsm AlgoClassTargetSource; AlgoClassTargetSource* algoTS = new AlgoClassTargetSource(octree,kernel); algoTS->execute(); FScalFMMEngine::algoTimer = algoTS; FScalFMMEngine::abstrct = algoTS; break; } default : std::cout<< "No algorithm found (probably for strange reasons) : "<< FScalFMMEngine::Algorithm <<" exiting" << std::endl; } } void intern_dealloc_handle(Callback_free_cell unUsed){ //this->~FInterEngine(); } void print_everything(){ octree->forEachLeaf([&](LeafClass * leaf){ ContainerClass * sources = leaf->getSrc(); ContainerClass * targets = leaf->getTargets(); const FVector& indexesSources = sources->getIndexes(); const FVector& indexesTargets = targets->getIndexes(); FSize nbPartSource = sources->getNbParticles(); FSize nbPartTarget = targets->getNbParticles(); for(int i=0 ; igetPositions()[0][i],sources->getPositions()[1][i],sources->getPositions()[2][i], sources->getPhysicalValues()[i], sources->getForcesX()[i],sources->getForcesY()[i],sources->getForcesZ()[i], sources->getPotentials()[i]); } for(int i=0 ; igetPositions()[0][i],targets->getPositions()[1][i],targets->getPositions()[2][i], targets->getPhysicalValues()[i], targets->getForcesX()[i],targets->getForcesY()[i],targets->getForcesZ()[i], targets->getPotentials()[i]); } }); } }; #endif