1/*
2 * VerletListM.hpp
3 *
4 * Created on: Oct 15, 2016
5 * Author: i-bird
6 */
7
8#ifndef OPENFPM_DATA_SRC_NN_VERLETLIST_VERLETLISTM_HPP_
9#define OPENFPM_DATA_SRC_NN_VERLETLIST_VERLETLISTM_HPP_
10
11#include "NN/VerletList/VerletNNIteratorM.hpp"
12#include "VerletList.hpp"
13
14
15/*! \brief Get the neighborhood iterator based on type
16 *
17 * \tparam dim dimensionality
18 * \tparam T type of space
19 * \tparam CellListImpl Cell-list implementation
20 * \tparam type of neighborhood
21 * \tparam PartIt Particle iterator
22 *
23 */
24template<unsigned int dim, typename T, typename CellListImpl, typename PartIt, int type>
25struct NNTypeM
26{
27 /*! \brief Get the neighborhood
28 *
29 * \param v particle positions
30 * \param xp Position of the particle p
31 * \param p id of the particle p
32 * \param cl Cell-list type implementation
33 * \param r_cut Cutoff radius
34 *
35 * \return the NN iterator
36 *
37 */
38 static inline auto get(const PartIt & it,
39 const typename CellListImpl::internal_vector_pos_type & pos,
40 const openfpm::vector<pos_v<typename CellListImpl::internal_vector_pos_type>> & v,
41 Point<dim,T> & xp,
42 size_t pp,
43 size_t p,
44 CellListImpl & cl,
45 T r_cut) -> decltype(cl.template getNNIterator<NO_CHECK>(0))
46 {
47 return cl.template getNNIterator<NO_CHECK>(cl.getCell(xp));
48 }
49};
50
51/*! \brief Get the neighborhood iterator based on type
52 *
53 * specialization for the case with NN CRS symmetric
54 *
55 * \tparam dim dimensionality
56 * \tparam T type of space
57 * \tparam CellListImpl Cell-list implementation
58 * \tparam PartIt Particle iterator
59 *
60 */
61template<unsigned int dim, typename T, typename CellListImpl, typename PartIt>
62struct NNTypeM<dim,T,CellListImpl,PartIt,VL_CRS_SYMMETRIC>
63{
64 /*! \brief Get the neighborhood
65 *
66 * \param it particle iterator
67 * \param v vector of the particles positions
68 * \param xp Position of the particle p
69 * \param p id of the particle p
70 * \param cl Cell-list type implementation
71 * \param r_cut Cutoff radius
72 *
73 * \return the NN iterator
74 *
75 */
76 static inline auto get(const PartIt & it,
77 const typename CellListImpl::internal_vector_pos_type & pos,
78 const openfpm::vector<pos_v<typename CellListImpl::internal_vector_pos_type>> & v,
79 Point<dim,T> & xp,
80 size_t pp,
81 size_t p,
82 CellListImpl & cl,
83 T r_cut) -> decltype(it.getNNIteratorCSRM(pos,v))
84 {
85 return it.getNNIteratorCSRM(pos,v);
86 }
87};
88
89/*! \brief Get the neighborhood iterator based on type
90 *
91 * specialization for the case with NN symmetric
92 *
93 * \tparam dim dimensionality
94 * \tparam T type of space
95 * \tparam CellListImpl Cell-list implementation
96 * \tparam PartIt particle iterator
97 *
98 */
99template<unsigned int dim, typename T, typename CellListImpl, typename PartIt>
100struct NNTypeM<dim,T,CellListImpl,PartIt,VL_SYMMETRIC>
101{
102 /*! \brief Get the neighborhood
103 *
104 * \param v vector of the particles positions
105 * \param xp Position of the particle p
106 * \param p id of the particle p
107 * \param cl Cell-list type implementation
108 * \param r_cut Cutoff radius
109 *
110 * \return the NN iterator
111 *
112 */
113 static inline auto get(const PartIt & it,
114 const typename CellListImpl::internal_vector_pos_type & pos,
115 const openfpm::vector<pos_v<typename CellListImpl::internal_vector_pos_type>> & v,
116 Point<dim,T> & xp,
117 size_t pp,
118 size_t p,
119 CellListImpl & cl,
120 T r_cut) -> decltype(cl.template getNNIteratorSym<NO_CHECK>(0,0,0,typename CellListImpl::internal_vector_pos_type(),openfpm::vector<pos_v<typename CellListImpl::internal_vector_pos_type>>()))
121 {
122 return cl.template getNNIteratorSym<NO_CHECK>(cl.getCell(xp),pp,p,pos,v);
123 }
124};
125
126
127
128/*! \brief Class for Verlet list implementation with Multiphase
129 *
130 * \tparam dim Dimensionality of the space
131 * \tparam T type of the space float, double ...
132 * \tparam CellListImpl Base structure that store the information
133 *
134 */
135template<unsigned int dim,
136 typename T,
137 unsigned int sh_byte ,
138 typename CellListImpl=CellListM<dim,T,sh_byte>,
139 typename transform = shift<dim,T>,
140 typename vector_pos_type = openfpm::vector<Point<dim,T>>,
141 typename VerletBase=VerletList<dim,T,Mem_fast<>,transform, vector_pos_type> >
142class VerletListM : public VerletBase
143{
144
145 //! Mask to get the high bits of a number
146 typedef boost::high_bit_mask_t<sh_byte> mask_high;
147
148 //! Mask to get the low bits of a number
149 typedef boost::low_bits_mask_t<sizeof(size_t)*8-sh_byte> mask_low;
150
151 /*! \brief Create the Verlet list from a given cell-list
152 *
153 * \param pos vector of positions
154 * \param pos2 vector of neighborhood particles position
155 * \param r_cut cut-off radius to get the neighborhood particles
156 * \param g_m Indicate form which particles to construct the verlet list. For example
157 * if we have 120 particles and g_m = 100, the Verlet list will be constructed only for the first
158 * 100 particles
159 * \param cl Cell-list elements to use to construct the verlet list
160 * \param opt options to create the verlet list like VL_SYMMETRIC or VL_NON_SYMMETRIC
161 *
162 */
163 inline void create(const vector_pos_type & pos,
164 const openfpm::vector<pos_v<vector_pos_type>> & pos2 ,
165 const openfpm::vector<size_t> & dom,
166 const openfpm::vector<subsub_lin<dim>> & anom,
167 size_t pp,
168 T r_cut,
169 size_t g_m,
170 CellListImpl & cl,
171 size_t opt)
172 {
173 if (opt == VL_CRS_SYMMETRIC)
174 {
175 create_<CellNNIteratorSymM<dim,CellListImpl,sh_byte,RUNTIME,NO_CHECK>,VL_CRS_SYMMETRIC>(pos,pos2,dom,anom,pp,r_cut,g_m,cl,opt);
176 }
177 else if (opt == VL_SYMMETRIC)
178 {
179 create_<decltype(cl.template getNNIteratorSym<NO_CHECK>(0,0,0,pos,pos2)),VL_SYMMETRIC>(pos,pos2,dom,anom,pp,r_cut,g_m,cl,opt);
180 }
181 else
182 {
183 create_<decltype(cl.template getNNIterator<NO_CHECK>(0)),VL_NON_SYMMETRIC>(pos,pos2,dom,anom,pp,r_cut,g_m,cl,opt);
184 }
185 }
186
187 /*! \brief Create the Verlet list from a given cell-list
188 *
189 * \param pos vector of positions
190 * \param pos2 vector of position for the neighborhood
191 * \param r_cut cut-off radius to get the neighborhood particles
192 * \param g_m Indicate form which particles to construct the verlet list. For example
193 * if we have 120 particles and g_m = 100, the Verlet list will be constructed only for the first
194 * 100 particles
195 * \param cli Cell-list elements to use to construct the verlet list
196 * \param dom list of domain cells with normal neighborhood
197 * \param anom list of domain cells with non-normal neighborhood
198 * \param opt options
199 *
200 */
201 template<typename NN_type, int type> inline void create_(const vector_pos_type & pos,
202 const openfpm::vector<pos_v<vector_pos_type>> & pos2 ,
203 const openfpm::vector<size_t> & dom,
204 const openfpm::vector<subsub_lin<dim>> & anom,
205 size_t pp,
206 T r_cut,
207 size_t g_m,
208 CellListImpl & cli,
209 size_t opt)
210 {
211 size_t end;
212
213 auto it = PartItNN<type,dim,vector_pos_type,CellListImpl>::get(pos,dom,anom,cli,g_m,end);
214
215/* this->cl_n.resize(end);
216 this->cl_base.resize(end*this->slot);
217 this->cl_n.fill(0);*/
218
219 this->init_to_zero(this->slot,end);
220
221 // square of the cutting radius
222 T r_cut2 = r_cut * r_cut;
223
224 // iterate the particles
225 while (it.isNext())
226 {
227 size_t i = it.get();
228 Point<dim,T> xp = pos.template get<0>(i);
229
230 // Get the neighborhood of the particle
231 NN_type NN = NNTypeM<dim,T,CellListImpl,decltype(it),type>::get(it,pos,pos2,xp,pp,i,cli,r_cut);
232
233 while (NN.isNext())
234 {
235 size_t nnp = NN.getP();
236 size_t v = NN.getV();
237 size_t nnp_a = NN.get();
238
239 Point<dim,T> xq = pos2.get(v).pos.template get<0>(nnp);
240
241 if (xp.distance2(xq) < r_cut2)
242 this->addPart(i,nnp_a);
243
244 // Next particle
245 ++NN;
246 }
247
248 ++it;
249 }
250 }
251
252public:
253
254 /*! Initialize the verlet list from an already filled cell-list
255 *
256 * \param cli external Cell-list
257 * \param pp phase of pos
258 * \param r_cut cutoff-radius
259 * \param pos vector of particle positions
260 * \param pos2 vector of particle position for the neighborhood
261 * \param g_m Indicate form which particles to construct the verlet list. For example
262 * if we have 120 particles and g_m = 100, the Verlet list will be constructed only for the first
263 * 100 particles
264 * \param opt options for the Verlet-list creation
265 *
266 */
267 void Initialize(CellListImpl & cli, size_t pp,
268 T r_cut, const vector_pos_type & pos,
269 const openfpm::vector<struct pos_v<vector_pos_type>> & pos2, size_t g_m,
270 size_t opt = VL_NON_SYMMETRIC)
271 {
272// this->cl_n.resize(g_m);
273// this->cl_base.resize(g_m*this->slot);
274
275 Point<dim,T> spacing = cli.getCellBox().getP2();
276
277 // Create with radius or not
278 bool wr = true;
279
280 for (size_t i = 0 ; i < dim ; i++)
281 {wr &= r_cut <= spacing.get(i);}
282
283 if (wr == true || opt == VL_SYMMETRIC)
284 {
285 openfpm::vector<subsub_lin<dim>> anom_c;
286 openfpm::vector<size_t> dom_c;
287
288 create(pos,pos2,dom_c,anom_c,pp,r_cut,g_m,cli,opt);
289 }
290 else
291 {
292 std::cerr << __FILE__ << ":" << __LINE__ << " error iterator with radius is not implemented yet " << std::endl;
293 }
294 }
295
296 /*! \brief Get the element-id in the cell
297 *
298 * \tparam i property to get
299 *
300 * \param part part id
301 * \param ele element id
302 *
303 * \return The element value
304 *
305 */
306 inline size_t getP(size_t part, size_t ele) const
307 {
308 return VerletBase::get(part,ele) & mask_low::sig_bits_fast;
309 }
310
311 /*! \brief Get the element vector in the cell
312 *
313 * \tparam i property to get
314 *
315 * \param part particle id
316 * \param ele element id
317 *
318 * \return The element value
319 *
320 */
321 inline size_t getV(size_t part, size_t ele) const
322 {
323 return (VerletBase::get(part,ele)) >> (sizeof(size_t)*8-sh_byte);
324 }
325
326 /*! \brief Get the Neighborhood iterator
327 *
328 * It iterate across all the neighborhood particles of a selected particle
329 *
330 * \param part_id particle id
331 *
332 * \return an interator across the neighborhood particles
333 *
334 */
335 template<unsigned int impl=NO_CHECK> inline VerletNNIteratorM<dim,VerletListM<dim,T,sh_byte,CellListImpl,transform,vector_pos_type,VerletBase>,sh_byte> getNNIterator(size_t part_id)
336 {
337 VerletNNIteratorM<dim,VerletListM<dim,T,sh_byte,CellListImpl,transform,vector_pos_type,VerletBase>,sh_byte> vln(part_id,*this);
338
339 return vln;
340 }
341};
342
343
344#endif /* OPENFPM_DATA_SRC_NN_VERLETLIST_VERLETLISTM_HPP_ */
345