1/*
2 * Domain_NN_calculator.hpp
3 *
4 * Created on: Nov 26, 2016
5 * Author: i-bird
6 */
7
8#ifndef SRC_DECOMPOSITION_DOMAIN_NN_CALCULATOR_CART_HPP_
9#define SRC_DECOMPOSITION_DOMAIN_NN_CALCULATOR_CART_HPP_
10
11#include <Vector/map_vector.hpp>
12#include "NN/CellList/ParticleItCRS_Cells.hpp"
13
14/*! \brief This class calculate processor domains and neighborhood
15 * of each processor domain
16 *
17 * \param dim Dimensionality
18 *
19 */
20template<unsigned int dim>
21class domain_nn_calculator_cart
22{
23 //! True if domain and anomalous domain cells are computed
24 bool are_domain_anom_computed;
25
26 /////////////////////////////// CRS //////////////////////
27
28 //! anomalous cell neighborhood for CRS
29 openfpm::vector<subsub<dim>> anom;
30
31 //! Set of anomalous CRS domain cells linearized
32 openfpm::vector<subsub_lin<dim>> anom_lin;
33
34 //! Set of normal domain cells for CRS
35 openfpm::vector<grid_key_dx<dim>> dom;
36
37 //! Set of normal CRS domain cells linearized
38 openfpm::vector<size_t> dom_lin;
39
40 ////////////////////////////////// DOMAIN CELLS ///////////////////////
41
42 //! Set of domain cells
43 openfpm::vector<grid_key_dx<dim>> dom_cells;
44
45 //! Set of linearized domain cells
46 openfpm::vector<size_t> dom_cells_lin;
47
48 //////////////////////////////////////////////////////////////
49
50 //! Processor box
51 Box<dim,long int> proc_box;
52
53 //! Processor cells-grid
54 grid_sm<dim,void> gs;
55
56 //! key with all coordinates set to one
57 grid_key_dx<dim> one;
58
59 /*! \brief Calculate the subdomain that are in the skin part of the domain
60 *
61 \verbatim
62
63 +---+---+---+---+---+---+
64 | 1 | 2 | 3 | 4 | 5 | 6 |
65 +---+---+---+---+---+---+
66 |27 | | 7 |
67 +---+ +---+
68 |26 | | 8 |
69 +---+ +---+
70 |25 | | 9 |
71 +---+ DOM1 +---+
72 |24 | |10 |
73 +---+ +---+
74 |23 | |11 |
75 +---+ +---+
76 |22 | |12 |
77 +---+-----------+---+---+
78 |21 | |13 |
79 +---+ +---+
80 |20 | DOM2 |14 |
81 +---+---+---+---+---+
82 |19 |18 |17 | 16|15 |
83 +---+---+---+---+---+ <----- Domain end here
84 |
85 ^ |
86 |_____________|
87
88
89 \endverbatim
90 *
91 * In some cases like symmetric with CRS Scheme The cells indicated with numbers has a non straigh-forward
92 * neighborhood. This function calculate the list of the domain cells with normal symmetric neighborhood type
93 * and compute a list of cells with more complex neighboring cells.
94 *
95 * \param sub_keys array that contain the position of the sub-sub-domains indicated with numbers
96 * in grid coordinates + for each its neighboring cells
97 *
98 * \param dom_cells list of all the domain cells
99 *
100 * \param dom_subsub cells with normal neighborhood
101 *
102 * \param loc_box array of local sub-sub-domain in grid coordinates
103 *
104 * \param proc_box Processor bounding box in local coordinates
105 *
106 *
107 */
108 void CalculateDomAndAnomCells(openfpm::vector<subsub<dim>> & sub_keys,
109 openfpm::vector<grid_key_dx<dim>> & dom_subsub,
110 openfpm::vector<grid_key_dx<dim>> & dom_cells,
111 const ::Box<dim,long int> & proc_box,
112 const openfpm::vector<::Box<dim, size_t>> & loc_box)
113 {
114 // Reset dom and dom_subsub
115 sub_keys.clear();
116 dom_subsub.clear();
117
118 size_t sz[dim];
119
120 // ----Grid size = proc_box.getHigh(j) - proc_box.getLow(j)
121 // +2 is padding
122
123 for (size_t j = 0 ; j < dim ; j++)
124 {sz[j] = proc_box.getHigh(j) - proc_box.getLow(j) + 2 + 1;}
125
126 gs.setDimensions(sz);
127
128 // Set the grid
129 grid_cpu<dim, aggregate<openfpm::vector<grid_key_dx<dim>> >> g(sz);
130 g.setMemory();
131
132 for (size_t i = 0 ; i < dim ; i++)
133 {one.set_d(i,1);}
134
135 // Calculate the csr neighborhood
136 openfpm::vector<std::pair<grid_key_dx<dim>,grid_key_dx<dim>>> csr;
137 NNcalc_csr(csr);
138
139 // Draw the domain on this grid
140 for (size_t i = 0 ; i < loc_box.size() ; i++)
141 {
142 grid_key_dx<dim> start;
143 grid_key_dx<dim> stop;
144
145 for (size_t j = 0 ; j < dim ; j++)
146 {
147 start.set_d(j,loc_box.template get<0>(i)[j] - proc_box.getLow(j) + 1);
148 stop.set_d(j,loc_box.template get<1>(i)[j] - proc_box.getLow(j) + 1);
149 }
150
151 grid_key_dx_iterator_sub<dim> sub(g.getGrid(),start,stop);
152
153 while (sub.isNext())
154 {
155 auto key = sub.get();
156
157 for (size_t j = 0 ; j < csr.size() ; j++)
158 {
159 grid_key_dx<dim> src = key + csr.get(j).first;
160 grid_key_dx<dim> dst = key + csr.get(j).second;
161 g.template get<0>(src).add(dst);
162 }
163
164 dom_cells.add(key - one);
165
166 ++sub;
167 }
168 }
169
170 // Span all the grid point and take all the sub-sub-domains that has a
171 // neighborhood non-consistent to the normal symmetric NN, and the one that
172 // are consistent to NN symmetric
173 grid_key_dx_iterator<dim> it(g.getGrid());
174
175 while (it.isNext())
176 {
177 auto key = it.get();
178
179 // Adding in the list of the non-normal neighborhood cells
180 if (g.template get<0>(key).size() == openfpm::math::pow(3,dim)/2+1)
181 {
182 // Add in the list of the normal neighborhood list
183 dom_subsub.add(key - one);
184 }
185 else if (g.template get<0>(key).size() != 0)
186 {
187 sub_keys.add();
188 sub_keys.last().subsub = key - one;
189 // Adding the neighborhood of the cell
190
191 sub_keys.last().NN_subsub.resize(g.template get<0>(key).size());
192
193 for (size_t i = 0 ; i < g.template get<0>(key).size() ; i++)
194 {sub_keys.last().NN_subsub.get(i) = g.template get<0>(key).get(i) - one;}
195 }
196
197 ++it;
198 }
199 }
200
201 /*! \brief Linearize the sub-sub-domains ids
202 *
203 * A subsub domain can be identified by a set of number (i,j).
204 * The linearization transform it into a number
205 *
206 * \param anom set of grid keys to linearize
207 * \param anom_lin linearized output
208 * \param shift shifting to add for the linearizaton
209 * \param gs information about the grid to linearize
210 *
211 */
212 void linearize_subsub(const openfpm::vector<subsub<dim>> & anom,
213 openfpm::vector<subsub_lin<dim>> & anom_lin,
214 const grid_key_dx<dim> & shift,
215 const grid_sm<dim,void> & gs)
216 {
217 anom_lin.clear();
218 for (size_t i = 0 ; i < anom.size() ; i++)
219 {
220 grid_key_dx<dim> tmp = anom.get(i).subsub + shift;
221 anom_lin.add();
222 anom_lin.last().subsub = gs.LinId(tmp);
223
224 long int self_cell = -1;
225
226 for (size_t j = 0 ; j < anom.get(i).NN_subsub.size() ; j++)
227 {
228 grid_key_dx<dim> tmp = anom.get(i).NN_subsub.get(j) + shift;
229 anom_lin.get(i).NN_subsub.add((long int)gs.LinId(tmp) - anom_lin.get(i).subsub);
230
231 // This indicate that for example in the neighborhood of one cell it-self is included in the list
232 // For example the cell 100 is in the neighborhood of the cell 100
233 if (anom_lin.get(i).NN_subsub.last() == 0)
234 self_cell = anom_lin.get(i).NN_subsub.size() - 1;
235 }
236
237 // if exist the self interacting cell (Example cell 100 neighborhood of cell 100), this cell MUST BE ALWAYS at the beginning
238 if (self_cell != -1)
239 {
240 // bring the self-cell into the beginning
241 size_t tmp = anom_lin.get(i).NN_subsub.get(0);
242 anom_lin.get(i).NN_subsub.get(0) = 0;
243 anom_lin.get(i).NN_subsub.get(self_cell) = tmp;
244 }
245 }
246 }
247
248public:
249
250 domain_nn_calculator_cart()
251 :are_domain_anom_computed(false)
252 {
253 }
254
255 /*! \brief Set parameters to calculate the cell neighborhood
256 *
257 * \param proc_box processor cells box
258 *
259 */
260 void setParameters(const Box<dim,long int> & proc_box)
261 {
262 this->proc_box = proc_box;
263 }
264
265 /*! \brief Set parameters to calculate the cell neighborhood
266 *
267 * \param loc_box set of local sub-domains
268 * \param shift to apply in the linearization
269 * \param gs grid of cells (for the processor domain)
270 *
271 */
272 void setNNParameters(openfpm::vector<::Box<dim, size_t>> & loc_box,
273 const grid_key_dx<dim> & shift,
274 const grid_sm<dim,void> & gs)
275 {
276 if (are_domain_anom_computed == false)
277 {
278 CalculateDomAndAnomCells(anom,dom,dom_cells,proc_box,loc_box);
279 are_domain_anom_computed = true;
280
281 dom_cells_lin.clear();
282 for (size_t i = 0 ; i < dom_cells.size() ; i++)
283 {
284 grid_key_dx<dim> tmp = dom_cells.get(i) + shift;
285 dom_cells_lin.add(gs.LinId(tmp));
286 }
287
288
289 dom_lin.clear();
290 for (size_t i = 0 ; i < dom.size() ; i++)
291 {
292 grid_key_dx<dim> tmp = dom.get(i) + shift;
293 dom_lin.add(gs.LinId(tmp));
294 }
295
296 linearize_subsub(anom,anom_lin,shift,gs);
297 }
298 }
299
300 /*! \brief Get the domain Cells
301 *
302 *
303 * \return The set of domain cells
304 *
305 */
306 openfpm::vector<size_t> & getDomainCells()
307 {
308 return dom_cells_lin;
309 }
310
311 /*! \brief Get the domain Cells
312 *
313 *
314 * \return The set of domain cells
315 *
316 */
317 openfpm::vector<size_t> & getCRSDomainCells()
318 {
319 return dom_lin;
320 }
321
322 /*! \brief Get the domain anomalous cells
323 *
324 *
325 * \return The set of anomalous cells
326 *
327 */
328 openfpm::vector<subsub_lin<dim>> & getCRSAnomDomainCells()
329 {
330 return anom_lin;
331 }
332
333
334 /*! \brief In case you have to recompute the indexes
335 *
336 *
337 */
338 void reset()
339 {
340 are_domain_anom_computed = false;
341 }
342};
343
344#endif /* SRC_DECOMPOSITION_DOMAIN_NN_CALCULATOR_CART_HPP_ */
345