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:
constexpr static const std::size_t child_count = 1 << Dim;
/// Node position type
using position_t = FPoint<FReal, Dim>;
using position_t = typename tree_t::position_t;
/// Node bounding box type
using box_t = FBox<position_t>;
using box_t = typename tree_t::box_t;
/// Interaction lists type
using interaction_list_t = std::unordered_set<FNode*>;
/// Children array type
......@@ -207,7 +207,7 @@ public:
* - 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
using data_t = NodeData;
......
......@@ -11,6 +11,31 @@
#include "FPrePostOrderNodeIterator.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
*
......@@ -32,7 +57,7 @@ public:
/// Particle container type
using particle_container_t = _ParticleContainer;
/// Particle type
using particle_t = typename _ParticleContainer::value_type;
using particle_t = typename particle_type<_ParticleContainer>::type;
/// Floating point numbers type
using FReal = typename particle_t::FReal;
/// Particle position type
......@@ -54,7 +79,9 @@ public:
friend node_t;
/// Level storage type
using level_t = typename node_t::level_t;
/// Morton index storage type
using morton_index_t = typename node_t::morton_index_t;
/// Print particles when printing tree or not
......
......@@ -36,7 +36,7 @@ struct FUnifFlopsKernel {
MatrixFlopsKernelClass _matrixFlopsKernel;
/// Class representing a particle
using particle_t = typename ContainerClass::value_type;
using particle_t = typename ContainerClass::particle_t;
/// Number of children for a node
constexpr static std::size_t child_count = Fpow(2, particle_t::position_t::Dim);
......
......@@ -9,20 +9,60 @@
namespace scalfmm {
namespace details {
template<typename Particle, class Allocator>
struct FVariadicParticleContainerBase {
template<typename... Types>
static auto getTypes(std::tuple<Types...>)
-> variadic_vector<Allocator, Types...>;
using type = decltype(getTypes(std::declval<typename Particle::data_t>()));
};
}
}
namespace details {
/**
* \brief Helper to generate FVariadicParticleContainer base class
*
* \copydetails FVariadicParticleContainer
*/
template<typename Particle, class Allocator>
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> >
class FVariadicParticleContainer
: public scalfmm::details::FVariadicParticleContainerBase<Particle, Allocator>::type
......@@ -30,10 +70,11 @@ class FVariadicParticleContainer
using FBase = typename scalfmm::details::FVariadicParticleContainerBase<Particle, Allocator>::type;
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;
/**
......@@ -60,7 +101,7 @@ public:
* \param particle Particle to push
*/
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:
* \param position The particle position
* \param args The particle attributes
*/
template<typename... Args>
void push(const FPoint<FReal>& position, Args... args) {
this->push(Particle(position, args...));
template<typename Position, typename... Args>
void push(const Position& position, Args... 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
public:
/// 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... >;
/// Expanded the Types list
/// Expand Types list
using types_tuple_t = scalfmm::
pack_expand_tuple< Types... >;
......@@ -84,18 +84,16 @@ public:
*/
template<typename... Ts>
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
constexpr static std::size_t Dim = _Dim;
/// Size of #data_t tuple
constexpr static std::size_t NbAttributes = std::tuple_size<data_t>::value - Dim;
/// Size of #tuple_data_t tuple
constexpr static std::size_t NbAttributes = std::tuple_size<tuple_data_t>::value - Dim;
/// Floating point type
using FReal = _FReal;
/// #data_t alias, required by the FVariadicParticleContainer
using attribute_tuple_t = data_t;
/// Position type, required by the FVariadicParticleContainer
using position_t = FPoint<FReal, Dim>;
......@@ -126,16 +124,16 @@ public:
sfinae_check<correct_attribute_list_size<Ts...>()> = 0>
FBasicParticle(const position_t& pos, Ts&&... ts) :
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,
std::forward<Ts>(ts)...
)
{}
/// Constructor from tuple equivalent to #data_t
/// Constructor from tuple equivalent to #tuple_data_t
template<typename... Ts>
FBasicParticle(const std::tuple<Ts...>& ts) :
data_t(ts)
tuple_data_t(ts)
{}
/**
......@@ -191,14 +189,14 @@ public:
/**
* \brief Convert particle to a tuple
*/
data_t& data() {
tuple_data_t& as_tuple() {
return *this;
}
/**
* \brief Convert particle to a tuple
*/
const data_t& data() const {
const tuple_data_t& as_tuple() const {
return *this;
}
......@@ -211,8 +209,8 @@ private:
template<typename... Ts, std::size_t... Is, std::size_t... Js>
FBasicParticle(inria::index_sequence<Is...>, inria::index_sequence<Js...>,
const FPoint<FReal, Dim>& pos, Ts&&... ts) :
data_t(pos[Is]..., std::forward<Ts>(ts)...,
typename std::tuple_element<Dim+Js+sizeof...(ts), data_t>::type(0)...)
tuple_data_t(pos[Is]..., std::forward<Ts>(ts)...,
typename std::tuple_element<Dim+Js+sizeof...(ts), tuple_data_t>::type(0)...)
{
//static_assert(sizeof...(Ts) == NbAttributes, "Parameter count is incorrect");
}
......@@ -225,7 +223,7 @@ private:
*/
template<std::size_t... Is>
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:
*/
template<std::size_t... 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;
}
......
......@@ -19,6 +19,8 @@
#include "Kernels/Generic/FGenericData.hpp"
#include "Utils/FOstreamTuple.hpp"
/**
* \brief Particle with a count attribute for use with FCountKernel
*
......@@ -66,7 +68,8 @@ using TestCountNodeData = FGenericData<test_count_data::multipole_t, test_count_
template<class CellClass, class ContainerClass>
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);
std::mutex mtx;
......@@ -99,7 +102,7 @@ struct FCountKernel {
return;
}
using particle_t = typename ContainerClass::value_type;
using particle_t = typename ContainerClass::particle_t;
std::cerr << "Checking particle counts\n";
......@@ -112,7 +115,7 @@ struct FCountKernel {
for(auto* leaf : tree.leaves()) {
for(auto p : *(leaf->getParticleContainer())) {
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 {
}
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)
: FBase(pos, i)
{
std::get<Dim>(this->data()) = ++idx;
std::get<Dim>(this->as_tuple()) = ++idx;
}
/// Constructor from position and types
......
......@@ -94,7 +94,7 @@ std::size_t expected_M2L(node_t* node, bool v = false) {
(k < coord[2] - 1 || k > coord[2] + 1)) {
if(v)
std::cout << std::make_tuple(i,j,k);
std::cout << '('<< i << ", " << j << ", "<< k << ')';
++count;
}
......
......@@ -20,12 +20,12 @@ using FReal = double;
const int NVals = 1;
const unsigned int ORDER = 3;
using FReal = double;
using position_t = FPoint<FReal>;
using container_t = FP2PParticleContainerIndexed<FReal,1,1,NVals>;
using matrix_kernel_t = FInterpMatrixKernelR<FReal>;
using cell_t = FChebCell<FReal,ORDER, 1, 1, NVals>;
using kernel_t = FChebKernel<FReal,cell_t,container_t,matrix_kernel_t,ORDER, NVals>;
template<class T, std::size_t N>
std::ostream& print_array(std::ostream& os, const T(&arr)[N]) {
os << '[';
......@@ -50,14 +50,14 @@ int main() {
// Create a particle container and fill it
container_t container{};
// particle : {position}, index, phys. val, 0...
container.push({-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({-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({-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({-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.755,-0.755,-0.755}, 0, 1, 0, 0, 0, 0);
container.push(position_t{-0.755,-0.755,-0.955}, 1, 1, 0, 0, 0, 0);
container.push(position_t{-0.755,-0.955,-0.755}, 2, 1, 0, 0, 0, 0);
container.push(position_t{-0.755,-0.955,-0.955}, 3, 1, 0, 0, 0, 0);
container.push(position_t{-0.955,-0.755,-0.755}, 4, 1, 0, 0, 0, 0);
container.push(position_t{-0.955,-0.755,-0.955}, 5, 1, 0, 0, 0, 0);
container.push(position_t{-0.955,-0.955,-0.755}, 6, 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;
......
......@@ -18,7 +18,7 @@ class testFBasicParticleContainer {
using FContainer = FBasicParticleContainer<FReal, 5, float>;
using FParticle = FContainer::FParticle;
using FParticleData = FParticle::data_t;
using FParticleData = FParticle::tuple_data_t;
static_assert(
std::is_same<
......@@ -68,14 +68,14 @@ private:
assert(container.size() == 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);
assert(container.size() == 2);
assert(container.getNbParticles() == 2);
assert(container[1] == part_vect[1].data() );
assert(container[1] == part_vect[1].as_tuple() );
}
void test_push_particle() {
......@@ -85,21 +85,21 @@ private:
assert(container.size() == 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]);
assert(container.size() == 2);
assert(container[1] == part_vect[1].data() );
assert(container[1] == part_vect[1].as_tuple() );
container.push(part_vect[2]);
assert(container.size() == 3);
assert(container[2] == part_vect[2].data() );
assert(container[2] == part_vect[2].as_tuple() );
container.push(part_vect[3]);
assert(container.size() == 4);
assert(container[3] == part_vect[3].data() );
assert(container[3] == part_vect[3].as_tuple() );
}
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