Commit 38de838e authored by COULAUD Olivier's avatar COULAUD Olivier

Mv files in ScalFMM-Tools project

parent 8067ae8b
// See LICENCE file at project root
// ==== CMAKE =====
// @FUSE_MPI
// @FUSE_BLAS
// ================
#include <memory>
#include "Utils/FGlobal.hpp"
//#include <mpi.h>
// include algo for linear tree
#include "inria/algorithm/distributed/mpi.hpp"
#include "inria/linear_tree/balance_tree.hpp"
// tree class
#include "GroupTree/Core/FGroupTree.hpp"
// symbolic data
#include "Components/FSymbolicData.hpp"
// cell class
#include "Kernels/Chebyshev/FChebCell.hpp"
// parameter
#include "Utils/FParameters.hpp"
#include "Utils/FParameterNames.hpp"
// GroupParticleContianer
#include "GroupTree/Core/FP2PGroupParticleContainer.hpp"
// file loader
#include "Files/FMpiFmaGenericLoader.hpp"
// FBox
#include "Adaptive/FBox.hpp"
// Group linear tree
#include "GroupTree/Core/FGroupLinearTree.hpp"
// Function for GroupLinearTree
#include "GroupTree/Core/FDistributedGroupTreeBuilder.hpp"
#include "Utils/FTic.hpp"
#include "Files/FFmaGenericLoader.hpp"
#include "Utils/FLeafBalance.hpp"
#include "Contribs/json.hpp"
static const int ORDER = 6;
using FReal = double;
using GroupCellClass = FChebCell<FReal, ORDER>;
using GroupCellUpClass = typename GroupCellClass::multipole_t;
using GroupCellDownClass = typename GroupCellClass::local_expansion_t;
using GroupCellSymbClass = FSymbolicData;
using GroupContainerClass = FP2PGroupParticleContainer<FReal>;
using GroupOctreeClass = FGroupTree<FReal,
GroupCellSymbClass,
GroupCellUpClass,
GroupCellDownClass, GroupContainerClass, 1, 4, FReal>;
// Structure for 1 particle
struct particle_t {
using position_t = FPoint<FReal>;
position_t pos;
FReal phi;
std::size_t morton_index;
const auto& position() const {
return pos;
}
const FPoint<FReal>& getPosition(){
return pos;
}
const auto& physicalValue() const{
return phi;
}
const auto& getPositions() const {
return pos;
}
int weight() const { return 1;}
friend constexpr auto morton_index(const particle_t& p) {
return p.morton_index;
}
};
void sortParticle(FPoint<FReal> * allParticlesToSort, int treeHeight, int groupSize, std::vector<std::vector<int>> & sizeForEachGroup, std::vector<MortonIndex> & distributedMortonIndex, FFmaGenericLoader<FReal>& loader, int nproc);
void createNodeRepartition(std::vector<MortonIndex> distributedMortonIndex, std::vector<std::vector<std::vector<MortonIndex>>>& nodeRepartition, int nproc, int treeHeight);
FSize getNbParticlesPerNode(FSize mpi_count, FSize mpi_rank, FSize total);
int main(int argc, char *argv[]) {
FTic time;
// Parameter definition
const FParameterNames LocalOptionBlocSize { {"-bs"}, "The size of the block of the blocked tree"};
const FParameterNames LocalOptionTreeChoice{ {"-let"}, "Build the LET Group Tree"};
// Parameter help
FHelpDescribeAndExit(argc, argv,
"Test the blocked tree created with linear tree." ,FParameterDefinitions::OctreeHeight,
FParameterDefinitions::InputFile,
LocalOptionBlocSize,
LocalOptionTreeChoice);
// Get parameters
// Get the groupSize
const int groupSize =
FParameters::getValue(argc,argv,LocalOptionBlocSize.options, 250);
// Get the file input
const char* const filename =
FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma");
// Get the treeHeight
const unsigned int TreeHeight =
FParameters::getValue(argc, argv, FParameterDefinitions::OctreeHeight.options, 5);
const bool letTree =
FParameters::getValue(argc,argv,LocalOptionTreeChoice.options,false);
// The level is the level of the leaf
int level = TreeHeight-1;
// Init MPI communicator
// Initialisation MPI Berenger
FMpi FMpiComm(argc,argv);
int nproc = FMpiComm.global().processCount();
// Initialisation MPI Quentin
inria::mpi::communicator mpi_comm(FMpiComm.global().getComm());
// Show job information
std::cout << "GroupTree building comparaison " << std::endl;
std::cout << "File name : " << filename << std::endl;
std::cout << "TreeHeight : " << TreeHeight << std::endl;
std::cout << "Block size : " << groupSize << std::endl;
std::cout << "------------------------------------------" << std::endl;
FMpiFmaGenericLoader<FReal> loaderParrallel(filename, FMpiComm.global());
FFmaGenericLoader<FReal> loader(filename);
// vector to stock all particles
FTic timer_1;
if(letTree){
std::vector<particle_t> myParticles(loaderParrallel.getMyNumberOfParticles());
// define the max level to sort particle
const std::size_t max_level = sizeof(particle_t::morton_index) * 8 / 3;
// define a box, used in the sort
const FBox<FPoint<FReal>> box{loaderParrallel.getBoxWidth(),loaderParrallel.getCenterOfBox()};
// iterate on all of my particles
for(FSize idxPart = 0; idxPart <loaderParrallel.getMyNumberOfParticles();++idxPart){
particle_t tmp;
// get the current particles
loaderParrallel.fillParticle(&tmp.pos,&tmp.phi);
// set the morton index of the current particle at the max_level
tmp.morton_index = inria::linear_tree::get_morton_index(
tmp.pos, box, max_level);
// set the weight of the particle
tmp.phi = 0.1;
// add the particle to my vector of particle
myParticles.at(idxPart) = tmp;
}
// Now i have all of my particles in a vector, they all have a morton index
// now we will sort them
inria::sort(mpi_comm,myParticles,
[](const auto& p1, const auto& p2) {
return p1.morton_index < p2.morton_index;
});
// Now i want to create the the linear tree
// a linear tree is a tree, with only the leaf
auto linear_tree =
inria::linear_tree::create_balanced_linear_tree_at_level(mpi_comm,
level,
box,
myParticles);
// Now i need to create a blocked linear tree, it's just a linear tree with
// more information
// declaration of the group linear tree
FGroupLinearTree<decltype(linear_tree)::value_type>group_linear_tree{mpi_comm};
group_linear_tree.create_local_group_linear_tree(
&linear_tree,
groupSize
);
// now i will to redistribute the particle according to the linear tree
// Redistribution of particles
inria::linear_tree::redistribute_particles(mpi_comm,
linear_tree,
myParticles);
// Now we need to modify the morton index of of all particle to
// have the morton index at le treeHeight-1
for(unsigned i = 0 ; i < myParticles.size(); ++i){
myParticles.at(i).morton_index = inria::linear_tree::get_morton_index(
myParticles.at(i).pos, box, level);
}
// Now we need to share the particle distribution to build the GroupTree
group_linear_tree.set_index_particle_distribution(myParticles);
// Now i can declare my groupTree
// it's a empty instance of the FGroupTree
GroupOctreeClass localGroupTree =
GroupOctreeClass::template get_block_tree_instance<GroupCellSymbClass, GroupCellUpClass,
GroupCellDownClass, GroupContainerClass>(TreeHeight,
groupSize,
loaderParrallel.getCenterOfBox(),
loaderParrallel.getBoxWidth());
// Now i can fill the localGroupTree
std::cout << "Start creating LET Blocked tree " << std::endl;
time.tic();
localGroupTree.create_tree(group_linear_tree,myParticles);
time.tac();
// Now i want to build a LET tree
// the LET tree is the Local Essential Tree
// It's a the same tree but we add block from other proc
// the block added are the blocked needed to post task for the
// P2P M2M and M2L interaction
// The first step is to add a unique index at all of group
//int nb_block = dstr_grp_tree_builder::set_cell_group_global_index(localGroupTree,mpi_comm);
//// now we can create LET
timer_1.tic();
localGroupTree.create_LET(group_linear_tree);
timer_1.tac();
mpi_comm.barrier();
nlohmann::json result;
std::string name = std::to_string(TreeHeight);
name += "_" + std::to_string(groupSize)+"_"+std::to_string(loader.getNumberOfParticles()) + ".json";
std::ifstream file(name);
if(mpi_comm.rank() == 0){
auto tree = time.elapsed();
auto let = timer_1.elapsed();
if(file.fail()){
// le fichier n'éxiste pas
result["TreeHeight"] = TreeHeight;
result["GroupSize"] = groupSize;
result["Filename"] = filename;
result["NbParticle"] = loaderParrallel.getNumberOfParticles();
result["LET_Blocked_tree"]["tree"] = tree;
result["LET_Blocked_tree"]["let"] = let;
result["LET_Blocked_tree"]["total"] = let+tree;
} else {
file >> result;
result["LET_Blocked_tree"]["tree"] = tree;
result["LET_Blocked_tree"]["let"] = let;
result["LET_Blocked_tree"]["total"] = let+tree;
}
std::ofstream out(name, std::ios::out | std::ios::app);
out << result << std::endl;
}
return 0;
} else {
//FFmaGenericLoader<FReal> loader(filename);
const FSize NbParticles = loader.getNumberOfParticles();
FPoint<FReal> * allParticlesToSort = new FPoint<FReal>[NbParticles];
FSize idxPart{};
for(idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
FReal physicalValue = 0.1;
loader.fillParticle(&allParticlesToSort[idxPart], &physicalValue);//Same with file or not
}
std::vector<MortonIndex> distributedMortonIndex;
std::vector<std::vector<int>> sizeForEachGroup;
sortParticle(allParticlesToSort, TreeHeight, groupSize, sizeForEachGroup, distributedMortonIndex, loader, nproc);
FP2PParticleContainer<FReal> allParticles;
for(idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
FReal physicalValue = 0.1;
allParticles.push(allParticlesToSort[idxPart], physicalValue);
}
// Put the data into the tree
time.tic();
GroupOctreeClass groupedTree(TreeHeight, loader.getBoxWidth(), loader.getCenterOfBox(), groupSize, &allParticles, sizeForEachGroup, true);
time.tac();
nlohmann::json result;
std::string name = std::to_string(TreeHeight);
name += "_" + std::to_string(groupSize)+"_"+std::to_string(loader.getNumberOfParticles()) + ".json";
std::ifstream file(name);
if(mpi_comm.rank() == 0){
if(file.fail()){
// le fichier n'existe pas
result["TreeHeight"] = TreeHeight;
result["GroupSize"] = groupSize;
result["Filename"] = filename;
result["NbParticle"] = loaderParrallel.getNumberOfParticles();
result["Group_tree"]["time"] = time.elapsed();
} else {
file >> result;
result["Group_tree"]["time"] = time.elapsed();
}
std::ofstream out(name, std::ios::out | std::ios::app);
out << result << std::endl;
}
return 0;
}
}
void sortParticle(FPoint<FReal> * allParticles, int treeHeight, int groupSize, std::vector<std::vector<int>> & sizeForEachGroup, std::vector<MortonIndex> & distributedMortonIndex, FFmaGenericLoader<FReal>& loader, int nproc)
{
//Structure pour trier
struct ParticleSortingStruct{
FPoint<FReal> position;
MortonIndex mindex;
};
// Création d'un tableau de la structure pour trier puis remplissage du tableau
const FSize nbParticles = loader.getNumberOfParticles();
ParticleSortingStruct* particlesToSort = new ParticleSortingStruct[nbParticles];
for(FSize idxPart = 0 ; idxPart < nbParticles ; ++idxPart){
const FTreeCoordinate host = FCoordinateComputer::GetCoordinateFromPosition<FReal>(loader.getCenterOfBox(), loader.getBoxWidth(),
treeHeight,
allParticles[idxPart]);
const MortonIndex particleIndex = host.getMortonIndex();
particlesToSort[idxPart].mindex = particleIndex;
particlesToSort[idxPart].position = allParticles[idxPart];
}
//Trie du nouveau tableau
FQuickSort<ParticleSortingStruct, FSize>::QsOmp(particlesToSort, nbParticles, [](const ParticleSortingStruct& v1, const ParticleSortingStruct& v2){
return v1.mindex <= v2.mindex;
});
//Replace tout dans l'ordre dans le tableau d'origine
for(FSize idxPart = 0 ; idxPart < nbParticles ; ++idxPart){
allParticles[idxPart] = particlesToSort[idxPart].position;
}
//Compte le nombre de feuilles
sizeForEachGroup.resize(treeHeight);
MortonIndex previousLeaf = -1;
int numberOfLeaf = 0;
for(FSize idxPart = 0 ; idxPart < nbParticles ; ++idxPart)
{
if(particlesToSort[idxPart].mindex != previousLeaf)
{
previousLeaf = particlesToSort[idxPart].mindex;
++numberOfLeaf;
}
}
//Calcul de la taille des groupes au niveau des feuilles
FLeafBalance balancer;
for(int processId = 0; processId < nproc; ++processId)
{
FSize size_last;
FSize countGroup;
FSize leafOnProcess = balancer.getRight(numberOfLeaf, nproc, processId) - balancer.getLeft(numberOfLeaf, nproc, processId);
size_last = leafOnProcess%groupSize;
countGroup = (leafOnProcess - size_last)/groupSize;
for(int i = 0; i < countGroup; ++i)
sizeForEachGroup[treeHeight-1].push_back(groupSize);
if(size_last > 0)
sizeForEachGroup[treeHeight-1].push_back((int)size_last);
}
//Calcul du working interval au niveau des feuilles
previousLeaf = -1;
int countLeaf = 0;
int processId = 0;
FSize leafOnProcess = balancer.getRight(numberOfLeaf, nproc, 0) - balancer.getLeft(numberOfLeaf, nproc, 0);
distributedMortonIndex.push_back(previousLeaf);
for(FSize idxPart = 0 ; idxPart < nbParticles ; ++idxPart)
{
if(particlesToSort[idxPart].mindex != previousLeaf)
{
previousLeaf = particlesToSort[idxPart].mindex;
++countLeaf;
if(countLeaf == leafOnProcess)
{
distributedMortonIndex.push_back(previousLeaf);
distributedMortonIndex.push_back(previousLeaf);
countLeaf = 0;
++processId;
leafOnProcess = balancer.getRight(numberOfLeaf, nproc, processId) - balancer.getLeft(numberOfLeaf, nproc, processId);
}
}
}
distributedMortonIndex.push_back(particlesToSort[nbParticles - 1].mindex);
//Calcul des working interval à chaque niveau
std::vector<std::vector<std::vector<MortonIndex>>> nodeRepartition;
createNodeRepartition(distributedMortonIndex, nodeRepartition, nproc, treeHeight);
//Pour chaque niveau calcul de la taille des groupe
for(int idxLevel = treeHeight - 2; idxLevel >= 0; --idxLevel)
{
processId = 0;
int countParticleInTheGroup = 0;
MortonIndex previousMortonCell = -1;
//cout << "Compute Level " << idxLevel << endl;
for(int idxPart = 0; idxPart < nbParticles; ++idxPart)
{
MortonIndex mortonCell = (particlesToSort[idxPart].mindex) >> (3*(treeHeight - 1 - idxLevel));
if(mortonCell <= nodeRepartition[idxLevel][processId][1]) //Si l'indice est dans le working interval
{
if(mortonCell != previousMortonCell) //Si c'est un nouvelle indice
{
++countParticleInTheGroup; //On le compte dans le groupe
previousMortonCell = mortonCell;
if(countParticleInTheGroup == groupSize) //Si le groupe est plein on ajoute le compte
{
sizeForEachGroup[idxLevel].push_back(groupSize);
countParticleInTheGroup = 0;
}
}
}
else //Si l'on change d'interval de process on ajoute ce que l'on a compté
{
if(countParticleInTheGroup > 0)
sizeForEachGroup[idxLevel].push_back(countParticleInTheGroup);
countParticleInTheGroup = 1;
previousMortonCell = mortonCell;
++processId;
}
}
if(countParticleInTheGroup > 0)
sizeForEachGroup[idxLevel].push_back(countParticleInTheGroup);
}
}
void createNodeRepartition(std::vector<MortonIndex> distributedMortonIndex, std::vector<std::vector<std::vector<MortonIndex>>>& nodeRepartition, int nproc, int treeHeight) {
nodeRepartition.resize(treeHeight, std::vector<std::vector<MortonIndex>>(nproc, std::vector<MortonIndex>(2)));
for(int node_id = 0; node_id < nproc; ++node_id){
nodeRepartition[treeHeight-1][node_id][0] = distributedMortonIndex[node_id*2];
nodeRepartition[treeHeight-1][node_id][1] = distributedMortonIndex[node_id*2+1];
}
for(int idxLevel = treeHeight - 2; idxLevel >= 0 ; --idxLevel){
nodeRepartition[idxLevel][0][0] = nodeRepartition[idxLevel+1][0][0] >> 3;
nodeRepartition[idxLevel][0][1] = nodeRepartition[idxLevel+1][0][1] >> 3;
for(int node_id = 1; node_id < nproc; ++node_id){
nodeRepartition[idxLevel][node_id][0] = FMath::Max(nodeRepartition[idxLevel+1][node_id][0] >> 3, nodeRepartition[idxLevel][node_id-1][0]+1); //Berenger phd :)
nodeRepartition[idxLevel][node_id][1] = nodeRepartition[idxLevel+1][node_id][1] >> 3;
}
}
}
FSize getNbParticlesPerNode(FSize mpi_count, FSize mpi_rank, FSize total){
if(mpi_rank < (total%mpi_count))
return ((total - (total%mpi_count))/mpi_count)+1;
return ((total - (total%mpi_count))/mpi_count);
}
// ==== CMAKE =====
// @FUSE_BLAS
// ================
// Keep in private GIT
// @FUSE_MPI
#include "../../Src/Utils/FGlobal.hpp"
// include algo for linear tree
#include "inria/algorithm/distributed/mpi.hpp"
#include "inria/linear_tree/balance_tree.hpp"
// tree class
#include "../../Src/GroupTree/Core/FGroupTree.hpp"
// symbolic data
#include "../../Src/Components/FSymbolicData.hpp"
// cell class
#include "../../Src/Kernels/Chebyshev/FChebCell.hpp"
// parameter
#include "../../Src/Utils/FParameters.hpp"
#include "../../Src/Utils/FParameterNames.hpp"
// GroupParticleContianer
#include "../../Src/GroupTree/Core/FP2PGroupParticleContainer.hpp"
// file loader
#include "../../Src/Files/FMpiFmaGenericLoader.hpp"
// FBox
#include "Adaptive/FBox.hpp"
// Group linear tree
#include "../../Src/GroupTree/Core/FGroupLinearTree.hpp"
// Function for GroupLinearTree
#include "../../Src/GroupTree/Core/FDistributedGroupTreeBuilder.hpp"
#include <memory>
static const int ORDER = 6;
using FReal = double;
using GroupCellClass = FChebCell<FReal, ORDER>;
using GroupCellUpClass = typename GroupCellClass::multipole_t;
using GroupCellDownClass = typename GroupCellClass::local_expansion_t;
using GroupCellSymbClass = FSymbolicData;
using GroupContainerClass = FP2PGroupParticleContainer<FReal>;
using GroupOctreeClass = FGroupTree<FReal,
GroupCellSymbClass,
GroupCellUpClass,
GroupCellDownClass, GroupContainerClass, 1, 4, FReal>;
// Structure for 1 particle
struct particle_t {
using position_t = FPoint<FReal>;
position_t pos;
FReal phi;
MortonIndex morton_index;
const auto& position() const {
return pos;
}
const FPoint<FReal>& getPosition(){
return pos;
}
const auto& physicalValue() const{
return phi;
}
const auto& getPositions() const {
return pos;
}
int weight() const { return 1;}
friend constexpr auto morton_index(const particle_t& p) {
return p.morton_index;
}
};
int main(int argc, char *argv[]) {
// Parameter definition
const FParameterNames LocalOptionBlocSize { {"-bs"}, "The size of the block of the blocked tree"};
// Parameter help
FHelpDescribeAndExit(argc, argv,
"Test the blocked tree created with linear tree." ,FParameterDefinitions::OctreeHeight,
FParameterDefinitions::InputFile,
LocalOptionBlocSize);
// Get parameters
// Get the groupSize
const int groupSize =
FParameters::getValue(argc,argv,LocalOptionBlocSize.options, 250);
// Get the file input
const char* const filename =
FParameters::getStr(argc,argv,FParameterDefinitions::InputFile.options, "../Data/test20k.fma");
// Get the treeHeight
const unsigned int TreeHeight =
FParameters::getValue(argc, argv, FParameterDefinitions::OctreeHeight.options, 5);
// The level is the level of the leaf
int level = TreeHeight-1;
// Init MPI communicator
// Initialisation MPI Berenger
FMpi FMpiComm(argc,argv);
// Initialisation MPI Quentin
inria::mpi::communicator mpi_comm(FMpiComm.global().getComm());
// Show job information
std::cout << "JOB INFORMATION " << std::endl;
std::cout << "File name : " << filename << std::endl;
std::cout << "TreeHeight : " << TreeHeight << std::endl;
std::cout << "Block size : " << groupSize << std::endl;
std::cout << "------------------------------------------" << std::endl;
std::cout << "Opening : " << filename << " ...";
FMpiFmaGenericLoader<FReal> loader(filename, FMpiComm.global());
std::cout << " done." << std::endl;
// vector to stock all particles
std::vector<particle_t> myParticles(loader.getMyNumberOfParticles());
// define the max level to sort particle
const std::size_t max_level = sizeof(particle_t::morton_index) * 8 / 3;
// define a box, used in the sort
const FBox<FPoint<FReal>> box{loader.getBoxWidth(),loader.getCenterOfBox()};
// iterate on all of my particles
for(FSize idxPart = 0; idxPart <loader.getMyNumberOfParticles();++idxPart){
particle_t tmp;
// get the current particles
loader.fillParticle(&tmp.pos,&tmp.phi);
// set the morton index of the current particle at the max_level
tmp.morton_index = inria::linear_tree::get_morton_index(
tmp.pos, box, max_level);
// set the weight of the particle
tmp.phi = 0.1;
// add the particle to my vector of particle
myParticles.at(idxPart) = tmp;
}
// Now i have all of my particles in a vector, they all have a morton index
// now we will sort them
std::cout << "Sorting particles ...";
inria::sort(mpi_comm,myParticles,
[](const auto& p1, const auto& p2) {
return p1.morton_index < p2.morton_index;
});
std::cout << " Done" << std::endl;
std::cout << " I have " << loader.getMyNumberOfParticles() << " particles ..." << std::endl;
std::cout << "For a total of " << loader.getNumberOfParticles() << " particles ..." << std::endl;
// Now i want to create the the linear tree
// a linear tree is a tree, with only the leaf
std::cout << "Create linear tree at level " << level << " ...";
auto linear_tree =
inria::linear_tree::create_balanced_linear_tree_at_level(mpi_comm,
level,
box,
myParticles);
std::cout << " done." << std::endl;
// Now i need to create a blocked linear tree, it's just a linear tree with
// more information
std::cout << "Creating blocked linear tree ...";
// declaration of the group linear tree
FGroupLinearTree<decltype(linear_tree)::value_type>group_linear_tree{mpi_comm};
// now i will fill it
// i can apply 2 methods
// - create_local_group_linear_tree
// - create_global_group_linear_tree
// the first function balance the linear tree according to particle (so he
// don't touch to the distribution )
// the second function balance the linear tree according to the number of
// block, he try to have group full on the left
//
// with a groupSize at 128, 890 leaf and 3 proc the distribution will be
// ___________________________________
// | Proc 0 | Proc 1 | Proc 2 |
// | | | |
// | 128 128 | 128 128 | 128 128 122 |
// |___________|_________|_____________|
group_linear_tree.create_local_group_linear_tree(
&linear_tree,
groupSize
);
std::cout << " Done" << std::endl;
// now i will to redistribute the particle according to the linear tree
std::cout << "Redistribute ...";
// Redistribution of particles
inria::linear_tree::redistribute_particles(mpi_comm,
linear_tree,
myParticles);
std::cout << " Done" << std::endl;
// Now we need to modify the morton index of of all particle to
// have the morton index at le treeHeight-1
MortonIndex minMidx=1,maxMidx=0;
for (int i =0 ; i< level ; ++i){
minMidx= minMidx <<3 ;
}
for(unsigned i = 0 ; i < myParticles.size(); ++i){
myParticles.at(i).morton_index = inria::linear_tree::get_morton_index(
myParticles.at(i).pos, box, level);
maxMidx =std::max(maxMidx, myParticles.at(i).morton_index);
minMidx =std::min(minMidx, myParticles.at(i).morton_index);
}
std::cout << " MinIndex: " << minMidx << " MaxIndex: " << maxMidx<<std::endl;
// Now we need to share the particle distribution to build the GroupTree
std::cout << "Share my particle distribution ...";
group_linear_tree.set_index_particle_distribution(myParticles);
std::cout << " done"<< std::endl;
// Now i can declare my groupTree
// it's a empty instance of the FGroupTree
GroupOctreeClass localGroupTree = GroupOctreeClass::template get_block_tree_instance<GroupCellSymbClass, GroupCellUpClass, GroupCellDownClass, GroupContainerClass>(TreeHeight,
groupSize,
loader.getCenterOfBox(),
loader.getBoxWidth());
// Now i can fill the localGroupTree
std::cout << "Creating tree ..." ;
localGroupTree.create_tree(group_linear_tree,myParticles);
std::cout << " done." << std::endl;
// now we can show the groupTree
localGroupTree.printInfoBlocks();
return 0;
}
// ==== CMAKE =====
// @FUSE_BLAS
// @FUSE_MPI
// ================
//
#include "../../Src/Utils/FGlobal.hpp"
// include algo for linear tree
#include "inria/algorithm/distributed/mpi.hpp"
#include "inria/linear_tree/balance_tree.hpp"
// tree class
#include "../../Src/GroupTree/Core/FGroupTree.hpp"
// symbolic data
#include "../../Src/Components/FSymbolicData.hpp"
// cell class
#include "../../Src/Kernels/Chebyshev/FChebCell.hpp"
// parameter
#include "../../Src/Utils/FParameters.hpp"
#include "../../Src/Utils/FParameterNames.hpp"
// GroupParticleContianer
#include "../../Src/GroupTree/Core/FP2PGroupParticleContainer.hpp"
// file loader
#include "../../Src/Files/FMpiFmaGenericLoader.hpp"
// FBox
#include "Adaptive/FBox.hpp"
// Group linear tree
#include "../../Src/GroupTree/Core/FGroupLinearTree.hpp"
// Function for GroupLinearTree
#include "../../Src/GroupTree/Core/FDistributedGroupTreeBuilder.hpp"
// Include validation Function
#include "../../Src/GroupTree/Core/FDistributedLETGroupTreeValidator.hpp"
#include <memory>