Commit 78da786a authored by incardon's avatar incardon

Added vector iterator

parent 9cc682a6
......@@ -38,7 +38,7 @@
*
*/
template<unsigned int dim, typename T, template<typename> class device_l=openfpm::device_cpu, typename Memory=HeapMemory, template<unsigned int, typename> class Domain=Box, template<typename, typename, typename, typename> class data_s = openfpm::vector>
template<unsigned int dim, typename T, template<typename> class device_l=openfpm::device_cpu, typename Memory=HeapMemory, template<unsigned int, typename> class Domain=Box, template<typename, typename, typename, typename, unsigned int> class data_s = openfpm::vector>
class CartDecomposition
{
public:
......@@ -52,7 +52,7 @@ private:
//! This is the access_key to data_s, for example in the case of vector
//! acc_key is size_t
typedef typename data_s<SpaceBox<dim,T>,device_l<SpaceBox<dim,T>>,Memory,openfpm::vector_grow_policy_default>::access_key acc_key;
typedef typename data_s<SpaceBox<dim,T>,device_l<SpaceBox<dim,T>>,Memory,openfpm::vector_grow_policy_default,openfpm::vect_isel<SpaceBox<dim,T>>::value >::access_key acc_key;
//! Subspace selected
//! access_key in case of grid is just the set of the index to access the grid
......@@ -62,7 +62,7 @@ private:
SpaceBox<dim,T> sub_domain;
//! the set of all local sub-domain as vector
data_s<SpaceBox<dim,T>,device_l<SpaceBox<dim,T>>,Memory,openfpm::vector_grow_policy_default> sub_domains;
data_s<SpaceBox<dim,T>,device_l<SpaceBox<dim,T>>,Memory,openfpm::vector_grow_policy_default, openfpm::vect_isel<SpaceBox<dim,T>>::value > sub_domains;
//! number of total sub-domain
size_t N_tot;
......
......@@ -234,6 +234,195 @@ public:
{
return v_cl;
}
/*! \brief Get the reference of the selected element
*
*
* \param p property to get (is an integer)
* \param v1 grid_key that identify the element in the grid
*
*/
template <unsigned int p>inline auto get(grid_dist_key_dx<dim> & v1) -> typename std::add_lvalue_reference<decltype(loc_grid.get(v1.getSub()).template get<p>(v1.getKey()))>::type
{
return loc_grid.get(v1.getSub()).template get<p>(v1.getKey());
}
};
/*! \brief This is a distributed grid
*
* Implementation of a distributed grid with id decomposition. A distributed grid is a grid distributed
* across processors. The decomposition is performed on the id of the elements
*
* [Examples]
*
* on 1D where the id is from 1 to N
* processor k take M contiguous elements
*
* on 3D where (for example)
* processor k take M id-connected elements
*
* \param dim Dimensionality of the grid
* \param T type of grid
* \param Decomposition Class that decompose the grid for example CartDecomposition
* \param Mem Is the allocator
* \param device type of base structure is going to store the data
*
*/
template<typename T, typename Decomposition,typename Memory , typename device_grid >
class grid_dist_id<1,T,Decomposition,Memory,device_grid>
{
// Ghost expansion
Box<1,size_t> ghost;
//! Local grids
Vcluster_object_array<device_grid> loc_grid;
//! Size of the grid on each dimension
size_t g_sz[1];
//! Communicator class
Vcluster & v_cl;
/*! \brief Get the grid size
*
* Get the grid size, given a domain, the resolution on it and another spaceBox
* it give the size on all directions of the local grid
*
* \param sp SpaceBox enclosing the local grid
* \param domain Space box enclosing the physical domain or part of it
* \param v_size grid size on this physical domain
*
* \return An std::vector representing the local grid on each dimension
*
*/
std::vector<size_t> getGridSize(SpaceBox<1,typename Decomposition::domain_type> & sp, Box<1,typename Decomposition::domain_type> & domain, size_t (& v_size)[1])
{
std::vector<size_t> tmp;
for (size_t d = 0 ; d < 1 ; d++)
{
// push the size of the local grid
tmp.push_back(g_sz[0]);
}
return tmp;
}
/*! \brief Get the grid size
*
* Get the grid size, given a spaceBox
* it give the size on all directions of the local grid
*
* \param sp SpaceBox enclosing the local grid
* \param sz array to fill with the local grid size on each dimension
*
*/
void getGridSize(SpaceBox<1,size_t> & sp, size_t (& v_size)[1])
{
for (size_t d = 0 ; d < 1 ; d++)
{
// push the size of the local grid
v_size[d] = sp.getHigh(d) - sp.getLow(d) + 1;
}
}
public:
//! constructor
grid_dist_id(Vcluster v_cl, Decomposition & dec, size_t (& g_sz)[1], Box<1,size_t> & ghost)
:ghost(ghost),loc_grid(NULL),v_cl(v_cl)
{
// fill the global size of the grid
for (int i = 0 ; i < 1 ; i++) {this->g_sz[i] = g_sz[i];}
// Create local memory
Create();
}
//! constructor
grid_dist_id(size_t (& g_sz)[1])
:v_cl(*global_v_cluster)
{
// fill the global size of the grid
for (int i = 0 ; i < 1 ; i++) {this->g_sz[i] = g_sz[i];}
// Create local memory
Create();
}
/*! \brief Create the grid on memory
*
*/
void Create()
{
size_t n_grid = 1;
// create local grids for each hyper-cube
loc_grid = v_cl.allocate<device_grid>(n_grid);
// Size of the grid on each dimension
size_t l_res[1];
// Calculate the local grid size
l_res[0] = g_sz[0] / v_cl.getProcessingUnits();
// Distribute the remaining
size_t residual = g_sz[0] % v_cl.getProcessingUnits();
if (v_cl.getProcessUnitID() < residual)
l_res[0]++;
// Set the dimensions of the local grid
loc_grid.get(0).template resize<Memory>(l_res);
}
/*! \brief It return an iterator of the bulk part of the grid with a specified margin
*
* For margin we mean that every point is at least m points far from the border
*
* \param m margin
*
* \return An iterator to a grid with specified margins
*
*/
grid_dist_iterator<1,device_grid> getDomainIterator()
{
grid_dist_iterator<1,device_grid> it(loc_grid,0);
return it;
}
//! Destructor
~grid_dist_id()
{
}
/*! \brief Get the Virtual Cluster machine
*
* \return the Virtual cluster machine
*
*/
Vcluster & getVC()
{
return v_cl;
}
/*! \brief Get the reference of the selected element
*
*
* \param p property to get (is an integer)
* \param v1 grid_key that identify the element in the grid
*
*/
template <unsigned int p>inline auto get(grid_dist_key_dx<1> & v1) -> typename std::add_lvalue_reference<decltype(loc_grid.get(v1.getSub()).template get<p>(v1.getKey()))>::type
{
return loc_grid.get(0).template get<p>(v1.getKey());
}
};
#endif
......@@ -53,6 +53,21 @@ class grid_dist_iterator
{
}
/*! \brief operator=
*
* assign
*
*/
grid_dist_iterator<dim,device_grid> & operator=(const grid_dist_iterator<dim,device_grid> & gdi)
{
g_c = gdi.g_c;
gList = gdi.gList;
a_it = gdi.a_it;
m = gdi.m;
return *this;
}
/*! \brief Get the next element
*
* \return the next grid_key
......
......@@ -50,11 +50,27 @@ BOOST_AUTO_TEST_CASE( grid_dist_id_iterator_test_use)
{
auto key = dom.get();
g_dist.template get<0>(key) = count;
// Count the point
count++;
++dom;
}
size_t count_check = 0;
dom = g_dist.getDomainIterator();
while (dom.isNext())
{
auto key = dom.get();
BOOST_REQUIRE_EQUAL(g_dist.template get<0>(key),count_check);
count_check++;
++dom;
}
// Get the virtual cluster machine
Vcluster & vcl = g_dist.getVC();
......
......@@ -20,6 +20,26 @@ class grid_dist_key_dx
public:
/*! \brief Get the local grid
*
* \return the id of the local grid
*
*/
size_t getSub()
{
return g_c;
}
/*! \brief Get the key
*
* \return the local key
*
*/
grid_key_dx<dim> getKey()
{
return key;
}
grid_dist_key_dx(int g_c, grid_key_dx<dim> key)
:g_c(g_c),key(key)
{
......
/*
* spaces.hpp
*
* Created on: Mar 10, 2015
* Author: Pietro Incardona
*/
#ifndef SPACES_HPP_
#define SPACES_HPP_
template<unsigned int dim, typename T> class space
{
public:
typedef boost::fusion::vector<> type;
typedef typename memory_traits_inte<type>::type memory_int;
typedef typename memory_traits_lin<type>::type memory_lin;
type data;
static const unsigned int max_prop = 0;
};
template<typename T> class space<1,T>
{
public:
typedef boost::fusion::vector<T> type;
typedef typename memory_traits_inte<type>::type memory_int;
typedef typename memory_traits_lin<type>::type memory_lin;
type data;
static const unsigned int x = 0;
static const unsigned int max_prop = 1;
};
template<typename T> class space<2,T>
{
public:
typedef boost::fusion::vector<T,T> type;
typedef typename memory_traits_inte<type>::type memory_int;
typedef typename memory_traits_lin<type>::type memory_lin;
type data;
static const unsigned int x = 0;
static const unsigned int y = 1;
static const unsigned int max_prop = 2;
};
template<typename T> class space<3,T>
{
public:
typedef boost::fusion::vector<T,T,T> type;
typedef typename memory_traits_inte<type>::type memory_int;
typedef typename memory_traits_lin<type>::type memory_lin;
type data;
static const unsigned int x = 0;
static const unsigned int y = 1;
static const unsigned int z = 2;
static const unsigned int max_prop = 3;
};
template<typename T> class space<4,T>
{
public:
typedef boost::fusion::vector<T,T,T,T> type;
typedef typename memory_traits_inte<type>::type memory_int;
typedef typename memory_traits_lin<type>::type memory_lin;
type data;
static const unsigned int x = 0;
static const unsigned int y = 1;
static const unsigned int z = 2;
static const unsigned int t = 3;
static const unsigned int max_prop = 4;
};
template<typename T> class space<5,T>
{
public:
typedef boost::fusion::vector<T,T,T,T,T> type;
typedef typename memory_traits_inte<type>::type memory_int;
typedef typename memory_traits_lin<type>::type memory_lin;
type data;
static const unsigned int max_prop = 5;
};
template<typename T> class space<6,T>
{
public:
typedef boost::fusion::vector<T,T,T,T,T,T> type;
typedef typename memory_traits_inte<type>::type memory_int;
typedef typename memory_traits_lin<type>::type memory_lin;
type data;
static const unsigned int max_prop = 6;
};
template<typename T> class space<7,T>
{
public:
typedef boost::fusion::vector<T,T,T,T,T,T,T> type;
typedef typename memory_traits_inte<type>::type memory_int;
typedef typename memory_traits_lin<type>::type memory_lin;
type data;
static const unsigned int max_prop = 7;
};
template<typename T> class space<8,T>
{
public:
typedef boost::fusion::vector<T,T,T,T,T,T,T,T> type;
typedef typename memory_traits_inte<type>::type memory_int;
typedef typename memory_traits_lin<type>::type memory_lin;
type data;
static const unsigned int max_prop = 8;
};
#endif /* SPACES_HPP_ */
/*
* space_key.hpp
*
* Created on: Mar 6, 2015
* Author: Pietro Incardona
*/
#ifndef SPACE_KEY_HPP_
#define SPACE_KEY_HPP_
/*! \brief grid_key_dx is the key to access any element in the grid
*
* grid_key_dx is the key to access any element in the grid
*
* \tparam dim dimensionality of the grid
* \tparam T type of the space float, double, complex, ...
*
*/
template<unsigned int dim, typename T>
class space_key_dx
{
public:
//! Constructor
space_key_dx()
{}
//! Constructor from buffer
space_key_dx(T (& k)[dim])
{
for (int i = 0 ; i < dim ; i++)
this->k[i] = k[i];
}
//! Constructor from buffer
space_key_dx(const T (& k)[dim])
{
for (int i = 0 ; i < dim ; i++)
this->k[i] = k[i];
}
//! Construct a grid key from a list of numbers
space_key_dx(const T v,const T...t)
{
k[dim-1] = v;
invert_assign(t...);
}
/*! \brief Set to zero the key
*/
inline void zero()
{
for (int i = 0 ; i < dim ; i++)
{
k[i] = 0;
}
}
/*! \brief Set to invalid the key
*/
inline void invalid()
{
for (int i = 0 ; i < dim ; i++)
{
k[i] = -1;
}
}
/* \brief Check if two key are the same
*
* \param key_t key to check
*
* \return true if the two key are identical
*
*/
template<unsigned int dim_t> bool operator==(space_key_dx<dim_t,T> & key_t)
{
if (dim != dim_t)
{
return false;
}
// Check the two key index by index
for (int i = 0 ; i < dim ; i++)
{
if (k[i] != key_t.k[i])
{
return false;
}
}
// identical key
return true;
}
//! set the grid key from a list of numbers
template<typename a, typename ...T>void set(a v, T...t)
{
k[dim-1] = v;
invert_assign(t...);
}
/*! \brief Get the i index
*
* \param i index to get
*
* \return the index value
*
*/
mem_id value(size_t i) const
{
return k[i];
}
/*! \brief Get the i index
*
*
* \param i index to get
*
* \return the index value
*
*/
mem_id get(size_t i) const
{
return k[i];
}
/*! \brief Set the i index
*
* Set the i index
*
* \param i index to set
* \param id value to set
*
*/
void set_d(size_t i, mem_id id)
{
#ifdef DEBUG
if (i >= dim)
std::cerr << "grid_key_dx error: " << __FILE__ << " " << __LINE__ << " try to access dimension " << i << " on a grid_key_dx of size " << dim << "\n";
#endif
k[i] = id;
}
//! structure that store all the index
mem_id k[dim];
private:
/*! \brief Recursively invert the assignment
*
* Recursively invert the assignment at compile-time
*
*/
template<typename a, typename ...T>void invert_assign(a v,T...t)
{
k[sizeof...(T)] = v;
invert_assign(t...);
}
template<typename a, typename ...T>void invert_assign(a v)
{
k[0] = v;
}
void invert_assign()
{
}
};
#endif /* SPACE_KEY_HPP_ */
/*
* Vector.hpp
*
* Created on: Mar 5, 2015
* Author: Pietro Incardona
*/
#ifndef VECTOR_HPP_
#define VECTOR_HPP_
#include "Space/space.hpp"
#define NO_ID false
#define ID true
/*! \brief Distributed vector
*
*
*
*/
template<typename space, typename prop, typename Box, typename Decomposition , typename Memory=HeapMemory, bool with_id=false>
class vector_dist
{
private:
//! Space Decomposition
Decomposition dec;
// Space for space position
grid_dist_id<1,space,Decomposition,Memory> pos;
// Space for properties
grid_dist_id<1,prop,Decomposition,Memory> prp;
// Virtual cluster
Vcluster & v_cl;
public:
/*! \brief Constructor
*
* \param number of elements
*
*/
vector_dist(size_t np)
:dec(Decomposition(*global_v_cluster)),v_cl(*global_v_cluster)
{
// resize the position vector
pos.resize(np);
// resize the properties vector
prp.resize(np);
// Create a valid decomposition of the space
// Get the number of processor and calculate the number of sub-domain
// for decomposition
size_t n_proc = v_cl.getProcessingUnits();
size_t n_sub = n_proc * SUB_UNIT_FACTOR;
// Calculate the maximum number (before merging) of sub-domain on
// each dimension
size_t div[space::size];
for (int i = 0 ; i < space::size ; i++)
{div[i] = round_big_2(pow(n_sub,1.0/space::size));}
// Create the sub-domains
dec.setParameters(div);
}
/*! \brief Get position of an object
*
* \param vec_key vector element
*
*/
template<unsigned int id> auto getPos(size_t vec_key) -> decltype(pos.template get<id>(vec_key))
{
return pos.template get<id>(vec_key);
}
/*! \brief Get the property of the object
*
* \param vec_key vector element
*
*/
template<unsigned int id> auto getProp(size_t vec_key) -> decltype(prp.template get<id>(vec_key))
{
return prp.template get<id>(vec_key);
}
/*! \brief It communicate the particle to the respective processor
*
*/
void map()
{
// allocate n vector with n = number of processors
// boost::shared_ptr<openfpm::vector<space>> (new openfpm::vector<space>[v_cl.getProcessingUnits()]);
// allocate n vector with n = number of processors
// boost::shared_ptr<openfpm::vector<prop>> (new openfpm::vector<space>[v_cl.getProcessingUnits()]);
// Contain the map of the processor should communicate
openfpm::vector<unsigned char> p_map;
// Contain the processor id of each particle (basically where they have to go)
openfpm::vector<size_t> lbl_p(pos.size());
// It contain the list of the processors it should to communicate
openfpm::vector<size_t> p_list;
auto it = pos.getIterator();
// Label all the particles it the processor id where they should go
while (it.isNext())