Commit 187db7b0 authored by Quentin Khan's avatar Quentin Khan

Rework FVariadicParticleContainer

The container expects that the particle exposes a method `as_tuple` that
converts the particle object to an std::tuple.

The container no longer hides the underlying container value_type. It
provides a particle_t alias to the particle type.

FTree will deduce its particle type from the container in two steps:
  - if the container exposes a particle_t type, it is used
  - otherwise, the value_type alias of the container is used
parent 2005f7ac
...@@ -190,9 +190,9 @@ public: ...@@ -190,9 +190,9 @@ public:
constexpr static const std::size_t child_count = 1 << Dim; constexpr static const std::size_t child_count = 1 << Dim;
/// Node position type /// Node position type
using position_t = FPoint<FReal, Dim>; using position_t = typename tree_t::position_t;
/// Node bounding box type /// Node bounding box type
using box_t = FBox<position_t>; using box_t = typename tree_t::box_t;
/// Interaction lists type /// Interaction lists type
using interaction_list_t = std::unordered_set<FNode*>; using interaction_list_t = std::unordered_set<FNode*>;
/// Children array type /// Children array type
...@@ -207,7 +207,7 @@ public: ...@@ -207,7 +207,7 @@ public:
* - position_t position() const method must exist * - position_t position() const method must exist
* *
*/ */
using particle_t = typename particle_container_t::value_type; using particle_t = typename tree_t::particle_t;
/// Node data structure /// Node data structure
using data_t = NodeData; using data_t = NodeData;
......
...@@ -11,6 +11,31 @@ ...@@ -11,6 +11,31 @@
#include "FPrePostOrderNodeIterator.hpp" #include "FPrePostOrderNodeIterator.hpp"
#include "UninitNodeMemoryManager.hpp" #include "UninitNodeMemoryManager.hpp"
#include "inria/meta.hpp"
/**
* \brief Extract the particle type from the container
*
* \tparam Range Container type
*/
template<class Range, class = void>
struct particle_type {
/// Particle type
using type = typename Range::value_type;
};
/**
* \brief Extract the particle type from the container
*
* \tparam Range Container type
*/
template<class Range>
struct particle_type<Range, inria::void_t<typename Range::particle_t>> {
/// Particle type
using type = typename Range::particle_t;
};
/** /**
* \brief Adaptive FMM tree * \brief Adaptive FMM tree
* *
...@@ -32,7 +57,7 @@ public: ...@@ -32,7 +57,7 @@ public:
/// Particle container type /// Particle container type
using particle_container_t = _ParticleContainer; using particle_container_t = _ParticleContainer;
/// Particle type /// Particle type
using particle_t = typename _ParticleContainer::value_type; using particle_t = typename particle_type<_ParticleContainer>::type;
/// Floating point numbers type /// Floating point numbers type
using FReal = typename particle_t::FReal; using FReal = typename particle_t::FReal;
/// Particle position type /// Particle position type
...@@ -54,7 +79,9 @@ public: ...@@ -54,7 +79,9 @@ public:
friend node_t; friend node_t;
/// Level storage type
using level_t = typename node_t::level_t; using level_t = typename node_t::level_t;
/// Morton index storage type
using morton_index_t = typename node_t::morton_index_t; using morton_index_t = typename node_t::morton_index_t;
/// Print particles when printing tree or not /// Print particles when printing tree or not
......
...@@ -36,7 +36,7 @@ struct FUnifFlopsKernel { ...@@ -36,7 +36,7 @@ struct FUnifFlopsKernel {
MatrixFlopsKernelClass _matrixFlopsKernel; MatrixFlopsKernelClass _matrixFlopsKernel;
/// Class representing a particle /// Class representing a particle
using particle_t = typename ContainerClass::value_type; using particle_t = typename ContainerClass::particle_t;
/// Number of children for a node /// Number of children for a node
constexpr static std::size_t child_count = Fpow(2, particle_t::position_t::Dim); constexpr static std::size_t child_count = Fpow(2, particle_t::position_t::Dim);
......
...@@ -9,20 +9,60 @@ ...@@ -9,20 +9,60 @@
namespace scalfmm { namespace scalfmm {
namespace details { namespace details {
template<typename Particle, class Allocator>
struct FVariadicParticleContainerBase { /**
* \brief Helper to generate FVariadicParticleContainer base class
template<typename... Types> *
static auto getTypes(std::tuple<Types...>) * \copydetails FVariadicParticleContainer
-> variadic_vector<Allocator, Types...>; */
template<typename Particle, class Allocator>
using type = decltype(getTypes(std::declval<typename Particle::data_t>())); struct FVariadicParticleContainerBase {
};
} /// Expand a tuple types and get the corresponding variadic_vector
} template<typename... Ts>
static auto expand(const std::tuple<Ts...>&)
-> variadic_vector<Allocator, Ts...>;
/// Type of the base class
using type = decltype(expand(std::declval<Particle>().as_tuple()));
};
}} // close namespace scalfmm::details
/**
* \brief Particle container defined from a structure
*
* transparently stores particles in a structure of arrays manner instead of an
* array of structures.
*
* \tparam Particle The particle descriptor to store
* \tparam Allocator The allocator to use
*
* The Particle type must define an `as_tuple` method that returns a tuple
* representation of the particle. It is expected in general to follow the form:
*
* ~~~
* posX, posY, poZ, attributes...
* ~~~
*
*
* *Example*:
*
* ~~~{.cpp}
* struct particle_t {
* double x, y;
* float phi;
*
* auto as_tuple() const {
* return std::make_tuple(x, y, phi);
* }
* };
*
* FVariadicparticlecontainer<particle_t> container;
* ~~~
*
*/
template<typename Particle, class Allocator = FAlignedAllocator<128,char> > template<typename Particle, class Allocator = FAlignedAllocator<128,char> >
class FVariadicParticleContainer class FVariadicParticleContainer
: public scalfmm::details::FVariadicParticleContainerBase<Particle, Allocator>::type : public scalfmm::details::FVariadicParticleContainerBase<Particle, Allocator>::type
...@@ -30,10 +70,11 @@ class FVariadicParticleContainer ...@@ -30,10 +70,11 @@ class FVariadicParticleContainer
using FBase = typename scalfmm::details::FVariadicParticleContainerBase<Particle, Allocator>::type; using FBase = typename scalfmm::details::FVariadicParticleContainerBase<Particle, Allocator>::type;
public: public:
using value_type = Particle;
using position_t = typename Particle::position_t;
using FReal = typename position_t::FReal;
/// Alias to the particle type
using particle_t = Particle;
// Inherit contructors
using FBase::FBase; using FBase::FBase;
/** /**
...@@ -60,7 +101,7 @@ public: ...@@ -60,7 +101,7 @@ public:
* \param particle Particle to push * \param particle Particle to push
*/ */
void push(const Particle& particle) { void push(const Particle& particle) {
this->push_back(static_cast<typename Particle::data_t>(particle)); this->push_back(particle.as_tuple());
} }
/** /**
...@@ -75,9 +116,10 @@ public: ...@@ -75,9 +116,10 @@ public:
* \param position The particle position * \param position The particle position
* \param args The particle attributes * \param args The particle attributes
*/ */
template<typename... Args> template<typename Position, typename... Args>
void push(const FPoint<FReal>& position, Args... args) { void push(const Position& position, Args... args) {
this->push(Particle(position, args...)); Particle temp_part{position, args...};
this->push(temp_part.as_tuple());
} }
/** /**
......
...@@ -64,10 +64,10 @@ class FBasicParticle : public scalfmm::pack_expand_tuple< scalfmm::pack<_Dim, _F ...@@ -64,10 +64,10 @@ class FBasicParticle : public scalfmm::pack_expand_tuple< scalfmm::pack<_Dim, _F
public: public:
/// Storage class : std::tuple<FReal,...(Dim times), Types...> /// Storage class : std::tuple<FReal,...(Dim times), Types...>
using data_t = scalfmm:: using tuple_data_t = scalfmm::
pack_expand_tuple< scalfmm::pack<_Dim, _FReal>, Types... >; pack_expand_tuple< scalfmm::pack<_Dim, _FReal>, Types... >;
/// Expanded the Types list /// Expand Types list
using types_tuple_t = scalfmm:: using types_tuple_t = scalfmm::
pack_expand_tuple< Types... >; pack_expand_tuple< Types... >;
...@@ -84,18 +84,16 @@ public: ...@@ -84,18 +84,16 @@ public:
*/ */
template<typename... Ts> template<typename... Ts>
constexpr static bool correct_attribute_list_size() { constexpr static bool correct_attribute_list_size() {
return std::tuple_size<data_t>::value >= sizeof...(Ts) + Dim; return std::tuple_size<tuple_data_t>::value >= sizeof...(Ts) + Dim;
} }
/// Space dimensions /// Space dimensions
constexpr static std::size_t Dim = _Dim; constexpr static std::size_t Dim = _Dim;
/// Size of #data_t tuple /// Size of #tuple_data_t tuple
constexpr static std::size_t NbAttributes = std::tuple_size<data_t>::value - Dim; constexpr static std::size_t NbAttributes = std::tuple_size<tuple_data_t>::value - Dim;
/// Floating point type /// Floating point type
using FReal = _FReal; using FReal = _FReal;
/// #data_t alias, required by the FVariadicParticleContainer
using attribute_tuple_t = data_t;
/// Position type, required by the FVariadicParticleContainer /// Position type, required by the FVariadicParticleContainer
using position_t = FPoint<FReal, Dim>; using position_t = FPoint<FReal, Dim>;
...@@ -126,16 +124,16 @@ public: ...@@ -126,16 +124,16 @@ public:
sfinae_check<correct_attribute_list_size<Ts...>()> = 0> sfinae_check<correct_attribute_list_size<Ts...>()> = 0>
FBasicParticle(const position_t& pos, Ts&&... ts) : FBasicParticle(const position_t& pos, Ts&&... ts) :
FBasicParticle(inria::make_index_sequence<Dim>(), FBasicParticle(inria::make_index_sequence<Dim>(),
inria::make_index_sequence<std::tuple_size<data_t>::value-sizeof...(ts)-Dim>(), inria::make_index_sequence<std::tuple_size<tuple_data_t>::value-sizeof...(ts)-Dim>(),
pos, pos,
std::forward<Ts>(ts)... std::forward<Ts>(ts)...
) )
{} {}
/// Constructor from tuple equivalent to #data_t /// Constructor from tuple equivalent to #tuple_data_t
template<typename... Ts> template<typename... Ts>
FBasicParticle(const std::tuple<Ts...>& ts) : FBasicParticle(const std::tuple<Ts...>& ts) :
data_t(ts) tuple_data_t(ts)
{} {}
/** /**
...@@ -191,14 +189,14 @@ public: ...@@ -191,14 +189,14 @@ public:
/** /**
* \brief Convert particle to a tuple * \brief Convert particle to a tuple
*/ */
data_t& data() { tuple_data_t& as_tuple() {
return *this; return *this;
} }
/** /**
* \brief Convert particle to a tuple * \brief Convert particle to a tuple
*/ */
const data_t& data() const { const tuple_data_t& as_tuple() const {
return *this; return *this;
} }
...@@ -211,8 +209,8 @@ private: ...@@ -211,8 +209,8 @@ private:
template<typename... Ts, std::size_t... Is, std::size_t... Js> template<typename... Ts, std::size_t... Is, std::size_t... Js>
FBasicParticle(inria::index_sequence<Is...>, inria::index_sequence<Js...>, FBasicParticle(inria::index_sequence<Is...>, inria::index_sequence<Js...>,
const FPoint<FReal, Dim>& pos, Ts&&... ts) : const FPoint<FReal, Dim>& pos, Ts&&... ts) :
data_t(pos[Is]..., std::forward<Ts>(ts)..., tuple_data_t(pos[Is]..., std::forward<Ts>(ts)...,
typename std::tuple_element<Dim+Js+sizeof...(ts), data_t>::type(0)...) typename std::tuple_element<Dim+Js+sizeof...(ts), tuple_data_t>::type(0)...)
{ {
//static_assert(sizeof...(Ts) == NbAttributes, "Parameter count is incorrect"); //static_assert(sizeof...(Ts) == NbAttributes, "Parameter count is incorrect");
} }
...@@ -225,7 +223,7 @@ private: ...@@ -225,7 +223,7 @@ private:
*/ */
template<std::size_t... Is> template<std::size_t... Is>
position_t position_impl(inria::index_sequence<Is...>) const{ position_t position_impl(inria::index_sequence<Is...>) const{
return position_t(std::get<Is>(this->data())...); return position_t(std::get<Is>(this->as_tuple())...);
} }
/** /**
...@@ -238,7 +236,7 @@ private: ...@@ -238,7 +236,7 @@ private:
*/ */
template<std::size_t... Is> template<std::size_t... Is>
void setPosition_impl(const position_t& pos, inria::index_sequence<Is...>) { void setPosition_impl(const position_t& pos, inria::index_sequence<Is...>) {
auto l = {std::get<Is>(this->data()) = pos[Is] ...}; auto l = {std::get<Is>(this->as_tuple()) = pos[Is] ...};
(void)l; (void)l;
} }
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include "Kernels/Generic/FGenericData.hpp" #include "Kernels/Generic/FGenericData.hpp"
#include "Utils/FOstreamTuple.hpp"
/** /**
* \brief Particle with a count attribute for use with FCountKernel * \brief Particle with a count attribute for use with FCountKernel
* *
...@@ -66,7 +68,8 @@ using TestCountNodeData = FGenericData<test_count_data::multipole_t, test_count_ ...@@ -66,7 +68,8 @@ using TestCountNodeData = FGenericData<test_count_data::multipole_t, test_count_
template<class CellClass, class ContainerClass> template<class CellClass, class ContainerClass>
struct FCountKernel { struct FCountKernel {
using particle_t = typename ContainerClass::value_type; using particle_t = typename ContainerClass::particle_t;
constexpr static std::size_t child_count = Fpow(2, particle_t::position_t::Dim); constexpr static std::size_t child_count = Fpow(2, particle_t::position_t::Dim);
std::mutex mtx; std::mutex mtx;
...@@ -99,7 +102,7 @@ struct FCountKernel { ...@@ -99,7 +102,7 @@ struct FCountKernel {
return; return;
} }
using particle_t = typename ContainerClass::value_type; using particle_t = typename ContainerClass::particle_t;
std::cerr << "Checking particle counts\n"; std::cerr << "Checking particle counts\n";
...@@ -112,7 +115,7 @@ struct FCountKernel { ...@@ -112,7 +115,7 @@ struct FCountKernel {
for(auto* leaf : tree.leaves()) { for(auto* leaf : tree.leaves()) {
for(auto p : *(leaf->getParticleContainer())) { for(auto p : *(leaf->getParticleContainer())) {
if(std::get<particle_t::COUNT>(p) != particle_count) { if(std::get<particle_t::COUNT>(p) != particle_count) {
std::cerr << p << "does not have the right particle count\n"; std::cerr << scalfmm::tuple_out(p) << "does not have the right particle count\n";
} }
} }
} }
......
...@@ -39,13 +39,13 @@ namespace scalfmm { ...@@ -39,13 +39,13 @@ namespace scalfmm {
} }
MockParticle() : FBase() { MockParticle() : FBase() {
std::get<Dim>(this->data()) = ++idx; std::get<Dim>(this->as_tuple()) = ++idx;
} }
MockParticle(const typename FBase::position_t& pos, std::size_t i) MockParticle(const typename FBase::position_t& pos, std::size_t i)
: FBase(pos, i) : FBase(pos, i)
{ {
std::get<Dim>(this->data()) = ++idx; std::get<Dim>(this->as_tuple()) = ++idx;
} }
/// Constructor from position and types /// Constructor from position and types
......
...@@ -94,7 +94,7 @@ std::size_t expected_M2L(node_t* node, bool v = false) { ...@@ -94,7 +94,7 @@ std::size_t expected_M2L(node_t* node, bool v = false) {
(k < coord[2] - 1 || k > coord[2] + 1)) { (k < coord[2] - 1 || k > coord[2] + 1)) {
if(v) if(v)
std::cout << std::make_tuple(i,j,k); std::cout << '('<< i << ", " << j << ", "<< k << ')';
++count; ++count;
} }
......
...@@ -20,12 +20,12 @@ using FReal = double; ...@@ -20,12 +20,12 @@ using FReal = double;
const int NVals = 1; const int NVals = 1;
const unsigned int ORDER = 3; const unsigned int ORDER = 3;
using FReal = double; using FReal = double;
using position_t = FPoint<FReal>;
using container_t = FP2PParticleContainerIndexed<FReal,1,1,NVals>; using container_t = FP2PParticleContainerIndexed<FReal,1,1,NVals>;
using matrix_kernel_t = FInterpMatrixKernelR<FReal>; using matrix_kernel_t = FInterpMatrixKernelR<FReal>;
using cell_t = FChebCell<FReal,ORDER, 1, 1, NVals>; using cell_t = FChebCell<FReal,ORDER, 1, 1, NVals>;
using kernel_t = FChebKernel<FReal,cell_t,container_t,matrix_kernel_t,ORDER, NVals>; using kernel_t = FChebKernel<FReal,cell_t,container_t,matrix_kernel_t,ORDER, NVals>;
template<class T, std::size_t N> template<class T, std::size_t N>
std::ostream& print_array(std::ostream& os, const T(&arr)[N]) { std::ostream& print_array(std::ostream& os, const T(&arr)[N]) {
os << '['; os << '[';
...@@ -50,14 +50,14 @@ int main() { ...@@ -50,14 +50,14 @@ int main() {
// Create a particle container and fill it // Create a particle container and fill it
container_t container{}; container_t container{};
// particle : {position}, index, phys. val, 0... // particle : {position}, index, phys. val, 0...
container.push({-0.755,-0.755,-0.755}, 0, 1, 0, 0, 0, 0); container.push(position_t{-0.755,-0.755,-0.755}, 0, 1, 0, 0, 0, 0);
container.push({-0.755,-0.755,-0.955}, 1, 1, 0, 0, 0, 0); container.push(position_t{-0.755,-0.755,-0.955}, 1, 1, 0, 0, 0, 0);
container.push({-0.755,-0.955,-0.755}, 2, 1, 0, 0, 0, 0); container.push(position_t{-0.755,-0.955,-0.755}, 2, 1, 0, 0, 0, 0);
container.push({-0.755,-0.955,-0.955}, 3, 1, 0, 0, 0, 0); container.push(position_t{-0.755,-0.955,-0.955}, 3, 1, 0, 0, 0, 0);
container.push({-0.955,-0.755,-0.755}, 4, 1, 0, 0, 0, 0); container.push(position_t{-0.955,-0.755,-0.755}, 4, 1, 0, 0, 0, 0);
container.push({-0.955,-0.755,-0.955}, 5, 1, 0, 0, 0, 0); container.push(position_t{-0.955,-0.755,-0.955}, 5, 1, 0, 0, 0, 0);
container.push({-0.955,-0.955,-0.755}, 6, 1, 0, 0, 0, 0); container.push(position_t{-0.955,-0.955,-0.755}, 6, 1, 0, 0, 0, 0);
container.push({-0.955,-0.955,-0.955}, 7, 1, 0, 0, 0, 0); container.push(position_t{-0.955,-0.955,-0.955}, 7, 1, 0, 0, 0, 0);
int tree_height = 4; int tree_height = 4;
......
...@@ -18,7 +18,7 @@ class testFBasicParticleContainer { ...@@ -18,7 +18,7 @@ class testFBasicParticleContainer {
using FContainer = FBasicParticleContainer<FReal, 5, float>; using FContainer = FBasicParticleContainer<FReal, 5, float>;
using FParticle = FContainer::FParticle; using FParticle = FContainer::FParticle;
using FParticleData = FParticle::data_t; using FParticleData = FParticle::tuple_data_t;
static_assert( static_assert(
std::is_same< std::is_same<
...@@ -68,14 +68,14 @@ private: ...@@ -68,14 +68,14 @@ private:
assert(container.size() == 1); assert(container.size() == 1);
assert(container.getNbParticles() == 1); assert(container.getNbParticles() == 1);
assert(container[0] == part_vect[0].data() ); assert(container[0] == part_vect[0].as_tuple() );
container.push(pos_vect[1], 6,7,8,9,10); container.push(pos_vect[1], 6,7,8,9,10);
assert(container.size() == 2); assert(container.size() == 2);
assert(container.getNbParticles() == 2); assert(container.getNbParticles() == 2);
assert(container[1] == part_vect[1].data() ); assert(container[1] == part_vect[1].as_tuple() );
} }
void test_push_particle() { void test_push_particle() {
...@@ -85,21 +85,21 @@ private: ...@@ -85,21 +85,21 @@ private:
assert(container.size() == 1); assert(container.size() == 1);
assert(container.getNbParticles() == 1); assert(container.getNbParticles() == 1);
assert(container[0] == part_vect[0].data() ); assert(container[0] == part_vect[0].as_tuple() );
container.push(part_vect[1]); container.push(part_vect[1]);
assert(container.size() == 2); assert(container.size() == 2);
assert(container[1] == part_vect[1].data() ); assert(container[1] == part_vect[1].as_tuple() );
container.push(part_vect[2]); container.push(part_vect[2]);
assert(container.size() == 3); assert(container.size() == 3);
assert(container[2] == part_vect[2].data() ); assert(container[2] == part_vect[2].as_tuple() );
container.push(part_vect[3]); container.push(part_vect[3]);
assert(container.size() == 4); assert(container.size() == 4);
assert(container[3] == part_vect[3].data() ); assert(container[3] == part_vect[3].as_tuple() );
} }
void test_positions() { void test_positions() {
......
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