Vector Multi Phase cell-list and Verlet
This example show how to use multi-phase cell lists and Verlet-list.More in general it show how to construct Verlet and Cell-list between multiple vector_dist.
Initialization
Here we Initialize the library, and we create a set of distributed vectors all forced to have the same decomposition. Each vector identify one phase.
- Note
- Be carefull on how you initialize the other phases. All the other phases must be forced to use the same decomposition. In order to do this we have to use the special constructor where we pass the decomposition from the first phase. The second parameter is just the the number of particles
openfpm_init(&argc,&argv);
size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
float r_cut = 0.05;
This class represent an N-dimensional box.
Implementation of VCluster class.
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...
Create phases
We initialize all the phases with particle randomly positioned in the space. Completed this iteration we redistribute the particles using the classical map, and we synchronize the ghost
- Warning
- we cannot use the same iterator for all the phases even if the number of particles for each phase is the same. Consider that the number of particles (per-processor) can be different. The case of the initialization ("before map") is the only case where we are sure that the number of particles per processor is the same for each phase
auto it = phases.get(0).getDomainIterator();
while (it.isNext())
{
auto p = it.get();
for (
size_t i = 0 ; i < phases.
size(); i++)
{
phases.get(i).getPos(p)[0] = (float)rand() / RAND_MAX;
phases.get(i).getPos(p)[1] = (float)rand() / RAND_MAX;
phases.get(i).getPos(p)[2] = (float)rand() / RAND_MAX;
}
++it;
}
for (size_t i = 0 ; i < 4 ; i++)
{
phases.get(i).map();
phases.get(i).ghost_get<>();
}
Multi phase Verlet-list
In general verlet-list can be constructed from the vector itself using getVerlerList()
- See also
- Vector 3 molecular dynamic with Verlet list
In the multi-phase case if we use such function on phase0 such function produce a Verlet list where for each particle of the phase0 we get the neighborhood particles within the phase0. Most of time we also want to construct Verlet-list across phases, for example between phase0 and phase1. Let suppose now that we want to construct a verlet-list that given the particles of the phase0 it return the neighborhood particles in phase1. In order to do this we can create a Cell-list from phase1. Once we have the Cell-list for phase 1 we give to createVerlet() the particle set of phase0, the Cell-list of phase1 and the cut-off radius. The function return a VerletList between phase0 and 1 that can be used to do computation.
{
auto CL_phase1 = phases.get(1).getCellList(r_cut);
auto NN_ver01 = createVerlet(phases.get(0),phases.get(1),CL_phase1,r_cut);
Once we have a Verlet-list, we can do easily computation with that. We can use the function getNNIterator() to get an iterator of the neighborhood particles for a specified particle. In this case for each particle of the phase0 we count the neighborhood particles in phase1
it = phases.get(0).getDomainIterator();
while (it.isNext())
{
auto p = it.get();
phases.get(0).getProp<0>(p) = 0;
auto Np = NN_ver01.template getNNIterator<NO_CHECK>(p.getKey());
while (Np.isNext())
{
auto q = Np.get();
phases.get(0).getProp<0>(p)++;
++Np;
}
++it;
}
}
From one phase to all
It is also possible to construct a Verlet-list from one phase to all the other phases. To do this we use the function createCellListM<2>() to first create a multi-phase cell-list. The template parameter is required to indicate how many bit to reserve for the phase information.
- Note
- In case of
- 2 bit mean that you can store up to 4 phases (2^62 number of particles for each phase)
- 3 bit mean that you can store up to 8 phases (2^61 number of particles for each phase)
Once created the multiphase-cell list from the phases. We can use the function createVerletM() to create a verlet-list from one phase to all the others. The function requires the particle for which we are constructing the verlet list, in this case the phase0, the Cell-list containing all the other phases and the cut-off radius.
float r_cut2 = r_cut*1.00001;
auto CL_all = createCellListM<2>(phases,r_cut2);
auto NNver0_all = createVerletM<2>(0,phases.get(0),phases,CL_all,r_cut);
Compute on a multiphase verlet-list is very similar to a non multi-phase. The only difference is that the function get() is substituted by two other functions getP() and getV() The first return the phase from where it come the particle the second it return the particle-id
it = phases.get(0).getDomainIterator();
while (it.isNext())
{
auto p = it.get();
auto Np = NNver0_all.template getNNIterator<NO_CHECK>(p.getKey());
phases.get(0).getProp<0>(p) = 0;
while (Np.isNext())
{
auto q = Np.getP();
auto ph_q = Np.getV();
phases.get(0).getProp<0>(p)++;
++Np;
}
++it;
}
Symmetric interaction case
The same functions exist also in the case we want to construct symmetric-verlet list.
- See also
- Vector 5 molecular dynamic with symmetric Verlet list For more details on how to use symmetric verlet-list in a real case.
In general the main differences can be summarized in
- we have to reset the forces or interaction variable(s)
- calculate the interaction p-q and apply the result to p and q at the same time
- merge with ghost_put the result is stored in the ghost part with the real particles
auto CL_phase1 = phases.get(1).getCellListSym(r_cut);
auto NN_ver01 = createVerletSym(phases.get(0),phases.get(1),CL_phase1,r_cut);
it = phases.get(0).getDomainAndGhostIterator();
while (it.isNext())
{
auto p = it.get();
phases.get(0).getProp<0>(p) = 0;
++it;
}
it = phases.get(0).getDomainIterator();
while (it.isNext())
{
auto p = it.get();
auto Np = NN_ver01.template getNNIterator<NO_CHECK>(p.getKey());
while (Np.isNext())
{
auto q = Np.get();
phases.get(0).getProp<0>(p)++;
phases.get(1).getProp<0>(q)++;
++Np;
}
++it;
}
phases.get(0).ghost_put<
add_,0>();
phases.get(1).ghost_put<
add_,0>();
}
This structure define the operation add to use with copy general.
For the case of a Verlet-list between the phase0 and all the other phases. The code remain very similar to the previous one the only differences is that we have to create a Multi-phase cell list from the vector of the phases. When we compute with the verlet-list list now the simple function get is substituted by the function getP and getV. In this example we are creating 4 multiphase symmetric verlet-list
- 0 to all
- 1 to all
- 2 to all
- 3 to all
The computation is an all to all
it = phases.get(0).getDomainAndGhostIterator();
while (it.isNext())
{
auto p = it.get();
phases.get(0).getProp<0>(p) = 0;
phases.get(1).getProp<0>(p) = 0;
phases.get(2).getProp<0>(p) = 0;
phases.get(3).getProp<0>(p) = 0;
++it;
}
CL_all = createCellListSymM<2>(phases,r_cut);
typedef decltype(createVerletSymM<2>(0,phases.get(0),phases,CL_all,r_cut)) verlet_type;
verlet_type NNver_all[4];
NNver_all[0] = createVerletSymM<2>(0,phases.get(0),phases,CL_all,r_cut);
NNver_all[1] = createVerletSymM<2>(1,phases.get(1),phases,CL_all,r_cut);
NNver_all[2] = createVerletSymM<2>(2,phases.get(2),phases,CL_all,r_cut);
NNver_all[3] = createVerletSymM<2>(3,phases.get(3),phases,CL_all,r_cut);
for (
size_t i = 0 ; i < phases.
size() ; i++)
{
it = phases.get(i).getDomainIterator();
while (it.isNext())
{
auto p = it.get();
auto Np = NNver_all[i].template getNNIterator<NO_CHECK>(p.getKey());
while (Np.isNext())
{
auto q = Np.getP();
auto ph_q = Np.getV();
phases.get(i).getProp<0>(p)++;
phases.get(ph_q).getProp<0>(q)++;
++Np;
}
++it;
}
}
phases.get(0).ghost_put<
add_,0>();
phases.get(1).ghost_put<
add_,0>();
phases.get(2).ghost_put<
add_,0>();
phases.get(3).ghost_put<
add_,0>();
Multi-phase cell-list usage
The multiphase cell-list that we constructed before to create a Verlet-list can be also used directly. In this case we accumulate on the property 0 of the phase 0 the distance of the near particles from all the phases
while (it2.isNext())
{
auto Np = CL_all.getNNIterator(CL_all.getCell(current_phase.
getPos(p)));
while (Np.isNext())
{
auto q = Np.getP();
auto ph_q = Np.getV();
current_phase.
getProp<0>(p) = norm(xp - xq);
++Np;
}
++it2;
}
This class implement the point shape in an N-dimensional space.
vect_dist_key_dx get()
Get the actual key.
auto getProp(vect_dist_key_dx vec_key) -> decltype(v_prp.template get< id >(vec_key.getKey()))
Get the property of an element.
auto getPos(vect_dist_key_dx vec_key) -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
vector_dist_iterator getIterator()
Get an iterator that traverse domain and ghost particles.
Finalize
At the very end of the program we have always de-initialize the library
Full code
#include "Vector/vector_dist.hpp"
#include "Decomposition/CartDecomposition.hpp"
#include "data_type/aggregate.hpp"
#include "NN/CellList/CellListM.hpp"
#include "Vector/vector_dist_multiphase_functions.hpp"
int main(int argc, char* argv[])
{
openfpm_init(&argc,&argv);
size_t bc[3]={PERIODIC,PERIODIC,PERIODIC};
float r_cut = 0.05;
auto it = phases.get(0).getDomainIterator();
while (it.isNext())
{
auto p = it.get();
for (
size_t i = 0 ; i < phases.
size(); i++)
{
phases.get(i).getPos(p)[0] = (float)rand() / RAND_MAX;
phases.get(i).getPos(p)[1] = (float)rand() / RAND_MAX;
phases.get(i).getPos(p)[2] = (float)rand() / RAND_MAX;
}
++it;
}
for (size_t i = 0 ; i < 4 ; i++)
{
phases.get(i).map();
phases.get(i).ghost_get<>();
}
{
auto CL_phase1 = phases.get(1).getCellList(r_cut);
auto NN_ver01 = createVerlet(phases.get(0),phases.get(1),CL_phase1,r_cut);
it = phases.get(0).getDomainIterator();
while (it.isNext())
{
auto p = it.get();
phases.get(0).getProp<0>(p) = 0;
auto Np = NN_ver01.template getNNIterator<NO_CHECK>(p.getKey());
while (Np.isNext())
{
auto q = Np.get();
phases.get(0).getProp<0>(p)++;
++Np;
}
++it;
}
}
float r_cut2 = r_cut*1.00001;
auto CL_all = createCellListM<2>(phases,r_cut2);
auto NNver0_all = createVerletM<2>(0,phases.get(0),phases,CL_all,r_cut);
it = phases.get(0).getDomainIterator();
while (it.isNext())
{
auto p = it.get();
auto Np = NNver0_all.template getNNIterator<NO_CHECK>(p.getKey());
phases.get(0).getProp<0>(p) = 0;
while (Np.isNext())
{
auto q = Np.getP();
auto ph_q = Np.getV();
phases.get(0).getProp<0>(p)++;
++Np;
}
++it;
}
{
auto CL_phase1 = phases.get(1).getCellListSym(r_cut);
auto NN_ver01 = createVerletSym(phases.get(0),phases.get(1),CL_phase1,r_cut);
it = phases.get(0).getDomainAndGhostIterator();
while (it.isNext())
{
auto p = it.get();
phases.get(0).getProp<0>(p) = 0;
++it;
}
it = phases.get(0).getDomainIterator();
while (it.isNext())
{
auto p = it.get();
auto Np = NN_ver01.template getNNIterator<NO_CHECK>(p.getKey());
while (Np.isNext())
{
auto q = Np.get();
phases.get(0).getProp<0>(p)++;
phases.get(1).getProp<0>(q)++;
++Np;
}
++it;
}
phases.get(0).ghost_put<
add_,0>();
phases.get(1).ghost_put<
add_,0>();
}
it = phases.get(0).getDomainAndGhostIterator();
while (it.isNext())
{
auto p = it.get();
phases.get(0).getProp<0>(p) = 0;
phases.get(1).getProp<0>(p) = 0;
phases.get(2).getProp<0>(p) = 0;
phases.get(3).getProp<0>(p) = 0;
++it;
}
CL_all = createCellListSymM<2>(phases,r_cut);
typedef decltype(createVerletSymM<2>(0,phases.get(0),phases,CL_all,r_cut)) verlet_type;
verlet_type NNver_all[4];
NNver_all[0] = createVerletSymM<2>(0,phases.get(0),phases,CL_all,r_cut);
NNver_all[1] = createVerletSymM<2>(1,phases.get(1),phases,CL_all,r_cut);
NNver_all[2] = createVerletSymM<2>(2,phases.get(2),phases,CL_all,r_cut);
NNver_all[3] = createVerletSymM<2>(3,phases.get(3),phases,CL_all,r_cut);
for (
size_t i = 0 ; i < phases.
size() ; i++)
{
it = phases.get(i).getDomainIterator();
while (it.isNext())
{
auto p = it.get();
auto Np = NNver_all[i].template getNNIterator<NO_CHECK>(p.getKey());
while (Np.isNext())
{
auto q = Np.getP();
auto ph_q = Np.getV();
phases.get(i).getProp<0>(p)++;
phases.get(ph_q).getProp<0>(q)++;
++Np;
}
++it;
}
}
phases.get(0).ghost_put<
add_,0>();
phases.get(1).ghost_put<
add_,0>();
phases.get(2).ghost_put<
add_,0>();
phases.get(3).ghost_put<
add_,0>();
auto it2 = current_phase.getIterator();
while (it2.isNext())
{
auto p = it2.get();
current_phase.getProp<0>(p) = 0.0;
auto Np = CL_all.getNNIterator(CL_all.getCell(current_phase.getPos(p)));
while (Np.isNext())
{
auto q = Np.getP();
auto ph_q = Np.getV();
current_phase.getProp<0>(p) = norm(xp - xq);
++Np;
}
++it2;
}
openfpm_finalize();
}