Attention une mise à jour du service Gitlab va être effectuée le mardi 30 novembre entre 17h30 et 18h00. Cette mise à jour va générer une interruption du service dont nous ne maîtrisons pas complètement la durée mais qui ne devrait pas excéder quelques minutes. Cette mise à jour intermédiaire en version 14.0.12 nous permettra de rapidement pouvoir mettre à votre disposition une version plus récente.

Commit 4542bd2a authored by ESTERIE Pierre's avatar ESTERIE Pierre
Browse files

cleaning new constructor and operators without order

parent 0f5d615f
......@@ -225,7 +225,7 @@ auto run(const int& tree_height, const int& group_size, const bool readFile, std
box3_type box3(box_width, box_center);
group_tree_type gtree(static_cast<std::size_t>(tree_height), runtime_order, box3,
static_cast<std::size_t>(group_size), *container);
static_cast<std::size_t>(group_size), static_cast<std::size_t>(group_size), *container);
using fmm_operator_type = count_kernels::particles::count_fmm_operator;
fmm_operator_type fmm_operator{};
......
......@@ -202,7 +202,7 @@ void run_level(Graph_container_type& graph, const int& tree_height, const int& g
using group_tree_type = scalfmm::component::group_tree<cell_type, leaf_type, box_type>;
group_tree_type gtree(static_cast<std::size_t>(tree_height), order, box, static_cast<std::size_t>(group_size),
container);
static_cast<std::size_t>(group_size), container);
/// Tree is filled
/////////////////////////////////////////////////////////////////////////////////////
///
......
......@@ -124,7 +124,7 @@ auto main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) -> int
time.tic();
box_type box(box_width, box_center);
group_tree_type gtree(static_cast<std::size_t>(tree_height), runtime_order, box,
static_cast<std::size_t>(group_size), container);
static_cast<std::size_t>(group_size), static_cast<std::size_t>(group_size), container);
time.tac();
std::cout << scalfmm::colors::yellow << "Group tree created in " << time.elapsed() << "ms\n"
<< scalfmm::colors::reset;
......
......@@ -137,7 +137,7 @@ auto main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) -> int
box_type box(box_width, box_center);
group_tree_type gtree(static_cast<std::size_t>(tree_height), order, box, static_cast<std::size_t>(group_size),
container);
static_cast<std::size_t>(group_size), container);
///
///
/// Set in nodes the particles sorted according to their Morton index.
......
......@@ -132,7 +132,7 @@ auto main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) -> int
box_type box(box_width, box_center);
group_tree_type gtree(static_cast<std::size_t>(tree_height), order, box, static_cast<std::size_t>(group_size),
*container);
static_cast<std::size_t>(group_size), *container);
///
///
/// Set in nodes the particles sorted according to their Morton index.
......
......@@ -141,7 +141,7 @@ auto run(const std::string& title, const std::string& input_file, const int &tre
box_type box(box_width, box3_center);
group_tree_type gtree(static_cast<std::size_t>(tree_height), order, box, static_cast<std::size_t>(group_size),
container);
static_cast<std::size_t>(group_size), container);
/////////////////////////////////////////////////////////////////////////////////////////////////
//// construct the interpolateor and the far-field
///
......@@ -160,7 +160,7 @@ auto run(const std::string& title, const std::string& input_file, const int &tre
std::cout.precision(15);
//
auto roots_1d = interpolator.roots(static_cast<std::size_t>(order));
auto roots_1d = interpolator.roots();
std::cout << "roots: " << roots_1d <<std::endl;
auto roots = scalfmm::tensor::generate_meshgrid<dimension>(roots_1d);
......@@ -212,7 +212,7 @@ auto run(const std::string& title, const std::string& input_file, const int &tre
// Apply the l2p operator
/// farfield operator
///
scalfmm::operators::apply_l2p_der<far_field_type::compute_gradient>(far_field, cell.clocals(), leaf, order);
scalfmm::operators::apply_l2p_der<far_field_type::compute_gradient>(far_field, cell.clocals(), leaf);
#ifndef toto
// for the next call nb_outputs_leaf = nb_outputs + dimension;
//scalfmm::operators::apply_l2p(far_field, cell.clocals(), leaf, order);
......
......@@ -111,7 +111,7 @@ auto run(const std::string& input_file, const std::string& output_file, const in
time.tic();
box_type box(box_width, box_center);
group_tree_type gtree(static_cast<std::size_t>(tree_height), order, box, static_cast<std::size_t>(group_size),
*container, dataSorted);
static_cast<std::size_t>(group_size), *container, dataSorted);
time.tac();
std::cout << scalfmm::colors::yellow << "Group tree created in " << time.elapsed() << "ms\n"
<< scalfmm::colors::reset;
......
......@@ -133,7 +133,7 @@ auto main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) -> int
<< scalfmm::colors::reset;
box_type box(box_width, box_center);
group_tree_type gtree(static_cast<std::size_t>(tree_height), order, box,
group_tree_type gtree(static_cast<std::size_t>(tree_height), order, box, static_cast<std::size_t>(group_size),
static_cast<std::size_t>(group_size), *container);
gtree.update_interaction_list();
int log_level = 5;
......
......@@ -112,10 +112,10 @@ namespace scalfmm::interpolation
/// \param order
/// \return the Chebyshev roots
///
[[nodiscard]] inline auto roots_impl(std::size_t order) const -> xt::xarray<value_type>
[[nodiscard]] inline auto roots_impl() const -> xt::xarray<value_type>
{
const value_type coeff = value_type(3.14159265358979323846264338327950) / (value_type(order));
return xt::cos(coeff * (xt::arange(int(order - 1), int(-1), -1) + 0.5));
const value_type coeff = value_type(3.14159265358979323846264338327950) / (value_type(this->order()));
return xt::cos(coeff * (xt::arange(int(this->order() - 1), int(-1), -1) + 0.5));
}
/**
* S_k(x) Lagrange fonction based on Chebyshev polynomials of first kind \f$
......@@ -195,7 +195,7 @@ namespace scalfmm::interpolation
[[nodiscard]] inline auto buffer_initialization_impl() const -> buffer_type { return empty{}; }
template<typename Cell>
inline auto apply_multipoles_preprocessing_impl(Cell& current_cell, std::size_t order) const -> void
inline auto apply_multipoles_preprocessing_impl(Cell& current_cell) const -> void
{
// using multipoles_container = typename Cell::multipoles_container;
// using fft_type = container::get_variadic_adaptor_t<xt::xarray<typename
......@@ -233,7 +233,7 @@ namespace scalfmm::interpolation
template<typename Cell, typename TupleScaleFactor>
inline auto apply_m2l_impl(Cell const& source_cell, Cell& target_cell, interaction_matrix_type const& k,
TupleScaleFactor scale_factor, std::size_t order, std::size_t tree_level,
TupleScaleFactor scale_factor, std::size_t tree_level,
[[maybe_unused]] buffer_type& products) const -> void
{
// auto const& transformed_multipoles = source_cell.ctransformed_multipoles();
......@@ -303,7 +303,7 @@ namespace scalfmm::interpolation
inline auto set_m_T_of_roots(size_type order) -> void
{
m_T_of_roots.resize(std::vector<std::size_t>(2, order));
auto roots = roots_impl(order);
auto roots = roots_impl();
// initialize chebyshev polynomials of root nodes: T_o(x_j)
/// m_T_of_roots[o,j] = T_o(x_j)
for(unsigned int o = 0; o < order; ++o)
......
......@@ -46,7 +46,7 @@ namespace count_kernels
};
using buffer_type = empty;
template<typename Cell>
void apply_multipoles_preprocessing(Cell& /*current_cell*/, std::size_t /*order*/)
void apply_multipoles_preprocessing(Cell& /*current_cell*/)
{
}
template<typename Cell>
......@@ -82,8 +82,7 @@ namespace count_kernels
//
};
template<typename Leaf, typename Cell>
inline void p2m(count_approximation const& interp, Leaf const& source_leaf, Cell& target_cell,
std::size_t /*order*/)
inline void p2m(count_approximation const& interp, Leaf const& source_leaf, Cell& target_cell)
{
auto const& target_symb = target_cell.csymbolics();
auto& multipoles = std::get<0>(target_cell.multipoles());
......@@ -92,7 +91,7 @@ namespace count_kernels
template<typename Cell>
inline void l2l(count_approximation const& /*interp*/, Cell const& parent_cell, std::size_t /*child_index*/,
Cell& child_cell, std::size_t /*order*/)
Cell& child_cell)
{
auto const& target_symb = child_cell.csymbolics();
auto& child_locals = std::get<0>(child_cell.locals());
......@@ -102,7 +101,7 @@ namespace count_kernels
template<typename Cell>
inline void m2m(count_approximation const& /*interp*/, Cell const& child_cell, std::size_t /*child_index*/,
Cell& parent_cell, std::size_t /*order*/)
Cell& parent_cell)
{
auto const& target_symb = parent_cell.csymbolics();
auto& parent_multipoles = std::get<0>(parent_cell.multipoles());
......@@ -112,7 +111,7 @@ namespace count_kernels
template<typename Cell>
inline void m2l(count_approximation const& /*interp*/, Cell const& source_cell, std::size_t /*neighbor_idx*/,
Cell& target_cell, std::size_t /*order*/, std::size_t /*tree_level*/,
Cell& target_cell, std::size_t /*tree_level*/,
typename count_approximation::buffer_type& /*buffer*/)
{
auto const& target_symb = target_cell.csymbolics();
......@@ -121,8 +120,7 @@ namespace count_kernels
target_locals += source_multipoles;
}
template<typename Cell, typename Leaf>
inline void l2p(count_far_field const& /*fmm_operator*/, Cell const& source_cell, Leaf& target_leaf,
std::size_t /*order*/)
inline void l2p(count_far_field const& /*fmm_operator*/, Cell const& source_cell, Leaf& target_leaf)
{
// auto interp = fmm_operator.far_field();
std::get<0>(*scalfmm::container::outputs_begin(target_leaf.particles())) =
......
......@@ -276,8 +276,8 @@ namespace scalfmm::operators
meta::for_each(S_der, [nnodes, inc](auto& c) { c.resize(nnodes * inc); });
}
auto call_polynomials = [&interp](auto x, std::size_t o, std::size_t n) { return interp.polynomials(x, n); };
auto call_derivative = [&interp](auto x, std::size_t o, std::size_t n) { return interp.derivative(x, n); };
auto call_polynomials = [&interp](auto x, std::size_t n) { return interp.polynomials(x, n); };
auto call_derivative = [&interp](auto x, std::size_t n) { return interp.derivative(x, n); };
// here, we process simd_size (i.e. inc) particles at each loop turn
for(std::size_t part = 0; part < vec_size; part += inc)
......
......@@ -11,38 +11,20 @@
namespace scalfmm::operators
{
// namespace laplace
// {
// template<typename Approximation>
// using fullLaplace = scalfmm::operators::fmm_operators<
// scalfmm::operators::near_field_operator<scalfmm::matrix_kernels::laplace::val_grad_one_over_r>,
// scalfmm::operators::far_field_operator<Approximation, true>>;
// } // namespace laplace
// template<typename Cell, typename Leaf, typename Approximation>
// inline void l2p(scalfmm::operators::fmm_operators<
// scalfmm::operators::near_field_operator<scalfmm::matrix_kernels::laplace::val_grad_one_over_r>,
// scalfmm::operators::far_field_operator<Approximation, true>> const& fmmOperator,
// Cell const& source_cell, Leaf& target_leaf, std::size_t order)
// template<typename Cell, typename Leaf, typename Approximation>
template<typename Cell, typename Leaf, typename Approximation>
inline void l2p(scalfmm::operators::far_field_operator<Approximation, true> const& far_field,
Cell const& source_cell, Leaf& target_leaf, std::size_t order)
Cell const& source_cell, Leaf& target_leaf)
{
// const auto& far_field = fmmOperator.far_field();
apply_l2p_der<true>(far_field, source_cell.clocals(), target_leaf, order);
apply_l2p_der<true>(far_field, source_cell.clocals(), target_leaf);
}
template<typename Cell, typename Leaf, typename Approximation, std::size_t Dimension>
inline void
// l2p(scalfmm::operators::fmm_operators<
// scalfmm::operators::near_field_operator<scalfmm::matrix_kernels::laplace::grad_one_over_r<Dimension>>,
// scalfmm::operators::far_field_operator<Approximation, true>> const& fmmOperator,
// Cell const& source_cell, Leaf& target_leaf, std::size_t order)
l2p(scalfmm::operators::far_field_operator<Approximation, true> const& far_field, Cell const& source_cell,
Leaf& target_leaf, std::size_t order)
inline void l2p(scalfmm::operators::far_field_operator<Approximation, true> const& far_field,
Cell const& source_cell, Leaf& target_leaf)
{
// const auto& far_field = fmmOperator.far_field();
apply_l2p_der<true>(far_field, source_cell.clocals(), target_leaf, order);
apply_l2p_der<true>(far_field, source_cell.clocals(), target_leaf);
}
} // namespace scalfmm::operators
#endif
......@@ -227,286 +227,6 @@ namespace scalfmm::component
return m_box.width(dimension) / (1 << leaf_level());
}
// /**
// * Minimal Constructor of GroupTree
// * @author benjamin.dufoyer@inria.fr
// * @param in__treeHeight size of the tree
// * @param in__nbElementsPerBlock block size
// * @param in_boxCenter box center
// * @param in_boxCorner box cornet
// * @param in_boxWidth bow witdh
// * @param in_boxWidthAtLeafLevel box width at leaf level
// */
// template<typename ParticleContainer>
// group_tree(
// int in_treeHeight,
// int in_nbElementsPerBlock,
// box_type const& box,
// FReal in_boxWidthAtLeafLevel
// ):
// _treeHeight(in__treeHeight),
// _nbElementsPerBlock(in__nbElementsPerBlock),
// boxCenter(in_boxCenter),
// boxCorner(in_boxCorner),
// boxWidth(in_boxWidth),
// boxWidthAtLeafLevel(in_boxWidthAtLeafLevel)
// {
// this->_cellBlocksPerLevel = new std::vector<CellGroupClass*>[_treeHeight];
// }
//
///
/// \brief group_tree
///
/// This constructor create a group tree from a particle container index.
/// The morton index are computed and the particles are sorted in a first stage.
/// Then the leaf level is done.
/// Finally the other level are proceed one after the other.
/// It should be easy to make it parallel using for and tasks.
/// If no limite give inLeftLimite = -1
/// \param tree_height
/// \param order
/// \param box
/// \param number_of_component_per_group
/// \param particle_container
/// \param particles_are_sorted
/// \param in_left_limit
/// \param in_top_level the root of the tree used in the FMM (2 execpt for periodic box)
///
// template<typename ParticleContainer>
template<typename ParticleContainer>
[[deprecated]] group_tree(std::size_t tree_height, std::size_t order, box_type const& box,
std::size_t number_of_component_per_group, ParticleContainer const& particle_container,
bool particles_are_sorted = false, int in_top_level = 2, int in_left_limit = -1)
: m_tree_height(tree_height)
, m_top_level(in_top_level)
, m_order(order)
, m_number_of_component_per_group(number_of_component_per_group)
, m_group_of_cell_per_level(tree_height)
, m_box(box)
{
std::cout << "Component per group = " << m_number_of_component_per_group << '\n';
static_assert(std::is_same_v<typename ParticleContainer::particle_type, particle_type>,
"group_tree : Particles contin in leafs are not the same as the ones in the container passed "
"as argument to this constructor.");
// auto number_of_particles{std::get<0>(particle_container.size())};
auto number_of_particles{particle_container.size()};
const std::size_t leaf_level{m_tree_height - 1};
// Storing group morton indexes.
std::vector<std::size_t> current_group_indexes(m_number_of_component_per_group);
// Storing the number of particles per leaf.
std::vector<std::size_t> number_of_particles_per_leaf(m_number_of_component_per_group);
// First we work at leaf level
// Convert position to morton index
/// Build the permutation to sort the particles according to their
/// morton. tuple_of_indexes is a vector of a tuple (idx, morton
/// idx)
auto tuple_of_indexes =
scalfmm::utils::get_morton_permutation(m_box, leaf_level, particle_container, particles_are_sorted);
std::size_t first_particle{0};
std::size_t last_particle{number_of_particles};
auto& groups_of_cell_at_leaf_level = m_group_of_cell_per_level.at(leaf_level);
auto box_width{box.width(0)};
auto box_corner{box.c1()};
std::size_t group_global_index{0};
while(first_particle != number_of_particles)
{
std::size_t size_of_group{0};
last_particle = first_particle;
while(size_of_group < m_number_of_component_per_group && last_particle < number_of_particles)
{
auto morton_index = std::get<0>(tuple_of_indexes[last_particle]);
if(size_of_group == 0 || current_group_indexes[size_of_group - 1] != morton_index)
{
current_group_indexes[size_of_group] = morton_index;
number_of_particles_per_leaf[size_of_group] = 1;
size_of_group += 1;
}
else
{
number_of_particles_per_leaf[size_of_group - 1] += 1;
}
++last_particle;
}
while(last_particle < number_of_particles &&
current_group_indexes[size_of_group - 1] == std::get<0>(tuple_of_indexes[last_particle]))
{
number_of_particles_per_leaf[size_of_group - 1] += 1;
++last_particle;
}
auto current_group_of_cell_pointer = std::make_shared<group_of_cell_type>(
current_group_indexes[0], current_group_indexes[size_of_group - 1] + 1, size_of_group,
group_global_index);
auto current_group_of_leaf_pointer = std::make_shared<group_of_leaf_type>(
current_group_indexes[0], current_group_indexes[size_of_group - 1] + 1, size_of_group,
last_particle - first_particle, group_global_index);
++group_global_index;
// initialize leaf at leaf level
auto begin_container = particle_container.cbegin();
std::size_t offset_particle{first_particle};
std::size_t component_id{0};
auto create_leaf = [&tuple_of_indexes, &component_id, &current_group_indexes, &box_corner, &box_width,
&tree_height, &leaf_level, &offset_particle, &number_of_particles_per_leaf,
&begin_container]() {
auto morton_index_of_leaf = current_group_indexes[component_id];
auto number_of_particles_in_leaf = number_of_particles_per_leaf[component_id];
auto coordinate = index::get_coordinate_from_morton_index<dimension>(morton_index_of_leaf);
auto width_center{index::get_box(box_corner, box_width, coordinate, tree_height, leaf_level)};
auto begin_of_particle = tuple_of_indexes.begin();
std::advance(begin_of_particle, offset_particle);
leaf_type sorted_leaf_to_move_in_block(number_of_particles_in_leaf, std::get<1>(width_center),
std::get<0>(width_center), morton_index_of_leaf);
for(std::size_t index_part = 0; index_part < number_of_particles_in_leaf; ++index_part)
{
auto source_index = std::get<1>(*begin_of_particle);
auto jump_to_particle = begin_container;
std::advance(jump_to_particle, source_index);
sorted_leaf_to_move_in_block.insert_particle(*jump_to_particle, index_part);
++begin_of_particle;
}
offset_particle += number_of_particles_per_leaf[component_id];
++component_id;
return sorted_leaf_to_move_in_block;
};
std::generate(std::begin(current_group_of_leaf_pointer->block()),
std::end(current_group_of_leaf_pointer->block()), create_leaf);
m_group_of_leaf.push_back(std::move(current_group_of_leaf_pointer));
component_id = 0;
auto create_cell = [&leaf_level, &component_id, &current_group_indexes, &box_corner, &box_width, &order,
&tree_height]() {
auto morton_index_of_cell = current_group_indexes[component_id];
auto coordinate = index::get_coordinate_from_morton_index<dimension>(morton_index_of_cell);
auto width_center{
index::get_box(box_corner, box_width, coordinate, tree_height, leaf_level)}; // +1 level
++component_id;
return cell_type(std::get<1>(width_center), std::get<0>(width_center), order, leaf_level,
morton_index_of_cell, coordinate);
};
// initialize cell agetNbCellGroupAtLevelt leaf level
std::generate(std::begin(current_group_of_cell_pointer->block()),
std::end(current_group_of_cell_pointer->block()), create_cell);
groups_of_cell_at_leaf_level.push_back(std::move(current_group_of_cell_pointer));
size_of_group = 0;
first_particle = last_particle;
}
//
// Building cell's levels
///
for(std::size_t level = tree_height - 2; level > 0; --level)
{
auto in_left_limit_ = (in_left_limit == -1 ? in_left_limit : in_left_limit >> dimension);
auto child_group_iterator = std::cbegin(m_group_of_cell_per_level[level + 1]);
auto end_child_group_iterator = std::cend(m_group_of_cell_per_level[level + 1]);
// Skip blocks that do not respect limit
// TODO: not sure about the shift
while(
child_group_iterator != end_child_group_iterator &&
(static_cast<int>((*child_group_iterator)->csymbolics().ending_index >> dimension) <= in_left_limit_))
{
++child_group_iterator;
}
// If lower level is empty or all blocks skiped stop here
if(child_group_iterator == end_child_group_iterator)
{
break;
}
auto const& group_symbolics = (*child_group_iterator)->csymbolics();
auto current_child_cell_index = group_symbolics.starting_index;
if(static_cast<int>(current_child_cell_index >> dimension) <= in_left_limit_)
{
current_child_cell_index = (std::size_t(in_left_limit_ + 1) << dimension);
}
std::size_t size_of_group{0};
while(child_group_iterator != end_child_group_iterator)
{
while(size_of_group < m_number_of_component_per_group &&
child_group_iterator != end_child_group_iterator)
{
// Carefull here is_inside() replaces exists() to avoid searching
if((size_of_group == 0 ||
current_group_indexes[size_of_group - 1] != (current_child_cell_index >> dimension)) &&
(*child_group_iterator)->exists(current_child_cell_index))
{
current_group_indexes[size_of_group] = (current_child_cell_index >> dimension);
size_of_group += 1;
current_child_cell_index = (((current_child_cell_index >> dimension) + 1) << dimension);
}
else
{
current_child_cell_index++;
}
// If we are at the end of the sub group, move to next
while(child_group_iterator != end_child_group_iterator &&
(*child_group_iterator)->csymbolics().ending_index <= current_child_cell_index)
{
++child_group_iterator;
// Update morton index
if(child_group_iterator != end_child_group_iterator &&
current_child_cell_index < (*child_group_iterator)->csymbolics().starting_index)
{
current_child_cell_index = (*child_group_iterator)->csymbolics().starting_index;
}
}
}
// If group is full
if(size_of_group == m_number_of_component_per_group ||
(size_of_group && child_group_iterator == end_child_group_iterator))
{
// Create a group
auto group_of_cell_pointer = std::make_shared<group_of_cell_type>(
current_group_indexes[0], current_group_indexes[size_of_group - 1] + 1, size_of_group);
std::size_t component_id{0};
auto create_cell_at_level = [&level, &component_id, &current_group_indexes, &box_corner,
&box_width, &order, &tree_height]() {
auto morton_index_of_cell = current_group_indexes[component_id];
auto coordinate = index::get_coordinate_from_morton_index<dimension>(morton_index_of_cell);
auto width_center{index::get_box(box_corner, box_width, coordinate, tree_height, level)};
++component_id;
return cell_type(std::get<1>(width_center), std::get<0>(width_center), order, level,
morton_index_of_cell, coordinate);
};
// initialize cell at leaf level
std::generate(std::begin(group_of_cell_pointer->block()),
std::end(group_of_cell_pointer->block()), create_cell_at_level);
m_group_of_cell_per_level[level].push_back(std::move(group_of_cell_pointer));
size_of_group = 0;
}
}
}
}
private:
/// @brief This function takes a vector of tuple storing indices.
/// In the the tuple the first element is the morton index of the particle.
......@@ -848,6 +568,63 @@ namespace scalfmm::component
}
}
// /**
// * Minimal Constructor of GroupTree
// * @author benjamin.dufoyer@inria.fr
// * @param in__treeHeight size of the tree
// * @param in__nbElementsPerBlock block size
// * @param in_boxCenter box center
// * @param in_boxCorner box cornet
// * @param in_boxWidth bow witdh
// * @param in_boxWidthAtLeafLevel box width at leaf level
// */
// template<typename ParticleContainer>
// group_tree(
// int in_treeHeight,
// int in_nbElementsPerBlock,
// box_type const& box,
// FReal in_boxWidthAtLeafLevel
// ):
// _treeHeight(in__treeHeight),
// _nbElementsPerBlock(in__nbElementsPerBlock),
// boxCenter(in_boxCenter),
// boxCorner(in_boxCorner),
// boxWidth(in_boxWidth),
// boxWidthAtLeafLevel(in_boxWidthAtLeafLevel)
// {
// this->_cellBlocksPerLevel = new std::vector<CellGroupClass*>[_treeHeight];
// }
//
///
/// \brief group_tree
///
/// This constructor create a group tree from a particle container index.