Commit d1ee4275 authored by Quentin Khan's avatar Quentin Khan

FNode can reinsert particles in tuple form

The particle containers access particles as tuples. The particles had to
be constructible from such a tuple to be reinserted when building the
tree.

FNode can now reinsert a particle that is not constructible from such a
tuple.
parent b268c0cc
......@@ -540,10 +540,10 @@ private:
* \param container Container to push into
* \param p Particle to push
*/
template<typename T,
scalfmm::sfinae::use_if<true, scalfmm::meta::has_push, T, particle_t> = nullptr>
void particle_push(T& container, const particle_t& p) {
container.push(p);
template<typename T, class... Args,
scalfmm::sfinae::use_if<true, scalfmm::meta::has_push, T, Args...> = nullptr>
void particle_push(T& container, const Args&... args) {
container.push(args...);
}
/**
......@@ -597,10 +597,19 @@ public:
*/
template<typename... Args>
void insert(const position_t& position, Args&&... args) {
this->insert(particle_t(position, std::forward<Args>(args)...));
if(! is_leaf()) {
std::size_t child_index = box_t::space_filling_curve_t::index(position, getBox().center());
getChild(child_index)->insert(position, args...);
} else {
this->set_ghost_owner(not_ghost_tag);
this->getParticleContainer()->reserve(this->getTree().leaf_max_particle_count());
particle_push(*(this->getParticleContainer()), position, args...);
if(getParticleContainer()->size() > getTree().leaf_max_particle_count()) {
split();
}
}
}
/**
* \brief Extracts a particle from a leaf
*
......@@ -942,6 +951,89 @@ private:
}
/**
* \brief Splits a particle tuple into a postion and attributes
*
* \param t Tuple to split
*
* \tparam Tuple Tuple type, std::get<I>(t) must extract the I_th element
*/
template<std::size_t... Is, std::size_t... Js, class Tuple>
static auto get_position_and_attributes_impl(
const Tuple& t,
inria::index_sequence<Is...>, inria::index_sequence<Js...>)
{
return std::make_pair(position_t(std::get<Is>(t)...),
std::make_tuple(std::get<Js+Dim>(t)...));
}
/**
* \brief Splits a particle tuple into a postion and attributes
*
* \param t Tuple to split
*
* \tparam Tuple Tuple type, std::get<I>(t) must extract the I_th element
*/
template<class Tuple>
static auto get_position_and_attributes(const Tuple& t)
{
return get_position_and_attributes_impl(
t,
inria::make_index_sequence<Dim>{} ,
inria::make_index_sequence<std::tuple_size<Tuple>::value - Dim>{});
}
/**
* \brief Reinsert particle in tree after spliting a container
*
* The #insert member function cannot be used to reinsert particles because
* the value_type of the container may not be a particle.
*
* This overload is used when the value_type is a tuple.
*
* \param p Tuple representation of the particle to insert
*/
template<class... Types>
void reinsert(std::tuple<Types...> p) {
reinsert_impl(get_position_and_attributes(p),
inria::make_index_sequence<sizeof...(Types)-Dim>{});
}
/**
* \brief Implementation of particle reinsertion
*
* \param pos_attrs The position and attributes tuple of the particle.
*
* \tparam Pair
* \parblock
* A std::pair like object that holds two attributes
*
* - `first` is the position of the particle
* - `second` is a tuple containing the particle attributes
* \endparblock
*
*/
template<class Pair, std::size_t... Is>
void reinsert_impl(const Pair& pos_attrs, inria::index_sequence<Is...>) {
this->insert(pos_attrs.first, std::get<Is>(pos_attrs.second)...);
}
/**
* \brief Reinsert particle in tree after spliting a container
*
* The #insert member function cannot be used to reinsert particles because
* the value_type of the container may not be a particle.
*
* This overload is used when the value_type is a particle.
*
* \param p Particle to insert
*/
void reinsert(const particle_t& p) {
this->insert(p);
}
/**
* \brief Reinsert particles once children have been added
*
......@@ -949,7 +1041,7 @@ private:
*/
void move_particles_to_children() {
for(auto&& p : *getParticleContainer()) {
this->insert(particle_t(p));
this->reinsert(p);
}
delete_particle_container();
}
......
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