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 | */ |
24 | template<unsigned int dim, typename T, typename CellListImpl, typename PartIt, int type> |
25 | struct 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 | */ |
61 | template<unsigned int dim, typename T, typename CellListImpl, typename PartIt> |
62 | struct 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 | */ |
99 | template<unsigned int dim, typename T, typename CellListImpl, typename PartIt> |
100 | struct 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 | */ |
135 | template<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> > |
142 | class 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 | |
252 | public: |
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 | |