Vector 4 complex properties
This example show how we can use complex properties in a vector
Initialization and vector creation
We first initialize the library and define useful constants
- See also
- Initialization
openfpm_init(&argc,&argv);
size_t bc[2]={PERIODIC,PERIODIC};
constexpr int scalar = 0;
constexpr int vector = 1;
constexpr int point = 2;
constexpr int list = 3;
constexpr int listA = 4;
constexpr int listlist = 5;
This class represent an N-dimensional box.
We also define a custom structure
struct A
{
float p1;
int p2;
A() {};
A(float p1, int p2)
:p1(p1),p2(p2)
{}
};
After we initialize the library we can create a vector with complex properties with the following line
float[3],
vd(4096,domain,bc,g);
This class implement the point shape in an N-dimensional space.
Implementation of 1-D std::vector like structure.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
In this this particular case every particle carry a scalar, a vector in form of float[3], a Point, a list in form of vector of float and a list of custom structures, and a vector of vector. In general particles can have properties of arbitrary complexity.
- Warning
- For arbitrary complexity mean that we can use any openfpm data structure with and arbitrary nested complexity. For example a openfpm::vector<aggregate<grid_cpu<openfpm::vector<aggregate<double,double[3]>>>,openfpm::vector<float>> is valid
particle
*
vector
/ \
/ \
grid vector<float>
/\
/ \
double double[3]
*
Our custom data-structure A is defined below. Note that this data-structure does not have pointers
struct A
{
float p1;
int p2;
A() {};
A(float p1, int p2)
:p1(p1),p2(p2)
{}
};
- Warning
- custom data structure are allowed only if they does not have pointer. In case they have pointer we have to define how to serialize our data-structure
- See also
- Vector 4 property serialization
Assign values to properties
Assign values to properties does not changes, from the simple case. Consider now that each particle has a list, so when we can get the property listA for particle p and resize such list with vd.getProp<listA>(p).resize(...). We can add new elements at the end with vd.getProp<listA>(p).add(...) and get some element of this list with vd.getProp<listA>(p).get(i). More in general vd.getProp<listA>(p) return a reference to the openfpm::vector contained by the particle.
auto it = vd.getDomainIterator();
while (it.isNext())
{
auto p = it.get();
vd.getPos(p)[0] = (float)rand() / RAND_MAX;
vd.getPos(p)[1] = (float)rand() / RAND_MAX;
vd.getProp<scalar>(p) = 1.0;
vd.getProp<vector>(p)[0] = 1.0;
vd.getProp<vector>(p)[1] = 1.0;
vd.getProp<vector>(p)[2] = 1.0;
vd.getProp<point>(p).get(0) = 1.0;
vd.getProp<point>(p).get(1) = 1.0;
vd.getProp<point>(p).get(2) = 1.0;
size_t n_cp = (float)10.0 * rand()/RAND_MAX;
vd.getProp<listA>(p).resize(n_cp);
for (size_t i = 0 ; i < n_cp ; i++)
{
vd.getProp<list>(p).add(i + 10);
vd.getProp<list>(p).add(i + 20);
vd.getProp<list>(p).add(i + 30);
vd.getProp<listA>(p).get(i) = A(i+10.0,i+20.0);
}
vd.getProp<listlist>(p).resize(2);
vd.getProp<listlist>(p).get(0).resize(2);
vd.getProp<listlist>(p).get(1).resize(2);
vd.getProp<listlist>(p).get(0).get(0) = 1.0;
vd.getProp<listlist>(p).get(0).get(1) = 2.0;
vd.getProp<listlist>(p).get(1).get(0) = 3.0;
vd.getProp<listlist>(p).get(1).get(1) = 4.0;
++it;
}
Mapping and ghost_get
Particles are redistributed across processors all properties are communicated but instead of using map we use map_list that we can use to select properties. A lot of time complex properties can be recomputed and communicate them is not a good idea. The same concept also apply for ghost_get. In general we choose which properties to communicate
- See also
- Mapping particles
-
Ghost
vd.map_list<scalar,vector,point,list,listA,listlist>();
vd.ghost_get<scalar,vector,point,listA,listlist>();
Output and VTK visualization
Vector with complex properties can be still be visualized, because unknown properties are automatically excluded
- See also
- Visualization, write VTK files
Print 4 particles in the ghost area
Here we print that the first 4 particles to show that the list of A and the list of list are filled and the ghosts contain the correct information
size_t fg = vd.size_local();
{
for ( ; fg < vd.size_local()+4 ; fg++)
{
std::cout << "List of A" << std::endl;
for (size_t i = 0 ; i < vd.getProp<listA>(fg).size() ; i++)
std::cout << "Element: " << i << " p1=" << vd.getProp<listA>(fg).get(i).p1 << " p2=" << vd.getProp<listA>(fg).get(i).p2 << std::endl;
std::cout << "List of list" << std::endl;
for (size_t i = 0 ; i < vd.getProp<listlist>(fg).size() ; i++)
{
for (size_t j = 0 ; j < vd.getProp<listlist>(fg).get(i).size() ; j++)
std::cout << "Element: " << i << " " << j << " " << vd.getProp<listlist>(fg).get(i).get(j) << std::endl;
}
}
}
size_t getProcessUnitID()
Get the process unit id.
Implementation of VCluster class.
Finalize
At the very end of the program we have always to de-initialize the library
Full code
#include "Vector/vector_dist.hpp"
int main(int argc, char* argv[])
{
openfpm_init(&argc,&argv);
size_t bc[2]={PERIODIC,PERIODIC};
constexpr int scalar = 0;
constexpr int vector = 1;
constexpr int point = 2;
constexpr int list = 3;
constexpr int listA = 4;
constexpr int listlist = 5;
struct A
{
float p1;
int p2;
A() {};
A(float p1, int p2)
:p1(p1),p2(p2)
{}
};
float[3],
vd(4096,domain,bc,g);
auto it = vd.getDomainIterator();
while (it.isNext())
{
auto p = it.get();
vd.getPos(p)[0] = (float)rand() / RAND_MAX;
vd.getPos(p)[1] = (float)rand() / RAND_MAX;
vd.getProp<scalar>(p) = 1.0;
vd.getProp<vector>(p)[0] = 1.0;
vd.getProp<vector>(p)[1] = 1.0;
vd.getProp<vector>(p)[2] = 1.0;
vd.getProp<point>(p).get(0) = 1.0;
vd.getProp<point>(p).get(1) = 1.0;
vd.getProp<point>(p).get(2) = 1.0;
size_t n_cp = (float)10.0 * rand()/RAND_MAX;
vd.getProp<listA>(p).resize(n_cp);
for (size_t i = 0 ; i < n_cp ; i++)
{
vd.getProp<list>(p).add(i + 10);
vd.getProp<list>(p).add(i + 20);
vd.getProp<list>(p).add(i + 30);
vd.getProp<listA>(p).get(i) = A(i+10.0,i+20.0);
}
vd.getProp<listlist>(p).resize(2);
vd.getProp<listlist>(p).get(0).resize(2);
vd.getProp<listlist>(p).get(1).resize(2);
vd.getProp<listlist>(p).get(0).get(0) = 1.0;
vd.getProp<listlist>(p).get(0).get(1) = 2.0;
vd.getProp<listlist>(p).get(1).get(0) = 3.0;
vd.getProp<listlist>(p).get(1).get(1) = 4.0;
++it;
}
vd.map_list<scalar,vector,point,list,listA,listlist>();
vd.ghost_get<scalar,vector,point,listA,listlist>();
vd.write("particles");
size_t fg = vd.size_local();
{
for ( ; fg < vd.size_local()+4 ; fg++)
{
std::cout << "List of A" << std::endl;
for (size_t i = 0 ; i < vd.getProp<listA>(fg).size() ; i++)
std::cout << "Element: " << i << " p1=" << vd.getProp<listA>(fg).get(i).p1 << " p2=" << vd.getProp<listA>(fg).get(i).p2 << std::endl;
std::cout << "List of list" << std::endl;
for (size_t i = 0 ; i < vd.getProp<listlist>(fg).size() ; i++)
{
for (size_t j = 0 ; j < vd.getProp<listlist>(fg).get(i).size() ; j++)
std::cout << "Element: " << i << " " << j << " " << vd.getProp<listlist>(fg).get(i).get(j) << std::endl;
}
}
}
openfpm_finalize();
}