| 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 | */ |
| 20 | template<unsigned int dim> |
| 21 | class 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 | |
| 248 | public: |
| 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 | |