| 1 | /* |
| 2 | * grid_dist_id_iterator_sub.hpp |
| 3 | * |
| 4 | * Created on: Feb 4, 2015 |
| 5 | * Author: Pietro Incardona |
| 6 | */ |
| 7 | |
| 8 | #ifndef GRID_DIST_ID_ITERATOR_HPP_ |
| 9 | #define GRID_DIST_ID_ITERATOR_HPP_ |
| 10 | |
| 11 | #define FREE 1 |
| 12 | #define FIXED 2 |
| 13 | #define ITERATION_ISOLATION 4 |
| 14 | |
| 15 | #include "Grid/grid_dist_key.hpp" |
| 16 | #include "VCluster/VCluster.hpp" |
| 17 | #include "util/GBoxes.hpp" |
| 18 | |
| 19 | #ifdef __NVCC__ |
| 20 | #include "SparseGridGpu/encap_num.hpp" |
| 21 | #endif |
| 22 | |
| 23 | template<unsigned int dim> |
| 24 | struct launch_insert_sparse_lambda_call |
| 25 | { |
| 26 | template<typename ec_type, typename lambda_t,typename coord_type> |
| 27 | __device__ inline static void call(ec_type & ec,lambda_t f, coord_type coord) |
| 28 | { |
| 29 | printf("Not implemented in this direction \n" ); |
| 30 | } |
| 31 | |
| 32 | template<typename ite_type> |
| 33 | __device__ inline static bool set_keys(grid_key_dx<3,int> & key, grid_key_dx<3,int> & keyg, ite_type & itg) |
| 34 | { |
| 35 | return false; |
| 36 | } |
| 37 | }; |
| 38 | |
| 39 | template<> |
| 40 | struct launch_insert_sparse_lambda_call<3> |
| 41 | { |
| 42 | template<typename grid_type, typename lambda_t1, typename lambda_t2,typename itd_type, typename coord_type> |
| 43 | __device__ inline static void call(grid_type & grid, |
| 44 | lambda_t1 f1, lambda_t2 f2, |
| 45 | unsigned int blockId, |
| 46 | itd_type itd, |
| 47 | coord_type & key, |
| 48 | coord_type & keyg,unsigned int offset, bool & is_block_empty, |
| 49 | bool is_in) |
| 50 | { |
| 51 | #ifdef __NVCC__ |
| 52 | |
| 53 | bool is_active = false; |
| 54 | if (is_in == true) |
| 55 | {is_active = f1(keyg.get(0),keyg.get(1),keyg.get(2));} |
| 56 | |
| 57 | if (is_active == true) |
| 58 | {is_block_empty = false;} |
| 59 | |
| 60 | __syncthreads(); |
| 61 | |
| 62 | if (is_block_empty == false) |
| 63 | { |
| 64 | auto ec = grid.insertBlock(blockId); |
| 65 | enc_num<decltype(grid.insertBlock(blockId))> ecn(ec,offset); |
| 66 | |
| 67 | if ( is_active == true) |
| 68 | { |
| 69 | f2(ecn,keyg.get(0),keyg.get(1),keyg.get(2)); |
| 70 | ec.template get<grid_type::pMask>()[offset] = 1; |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | #endif |
| 75 | } |
| 76 | |
| 77 | template<typename ite_type> |
| 78 | __device__ inline static bool set_keys(grid_key_dx<3,int> & key, grid_key_dx<3,int> & keyg, ite_type & itg) |
| 79 | { |
| 80 | #ifdef __NVCC__ |
| 81 | |
| 82 | key.set_d(0,threadIdx.x + blockIdx.x * blockDim.x + itg.start.get(0)); |
| 83 | key.set_d(1,threadIdx.y + blockIdx.y * blockDim.y + itg.start.get(1)); |
| 84 | key.set_d(2,threadIdx.z + blockIdx.z * blockDim.z + itg.start.get(2)); |
| 85 | |
| 86 | keyg.set_d(0,key.get(0) + itg.origin.get(0)); |
| 87 | keyg.set_d(1,key.get(1) + itg.origin.get(1)); |
| 88 | keyg.set_d(2,key.get(2) + itg.origin.get(2)); |
| 89 | |
| 90 | if (key.get(0) > itg.stop.get(0) || key.get(1) > itg.stop.get(1) || key.get(2) > itg.stop.get(2) || |
| 91 | key.get(0) < itg.start_base.get(0) || key.get(1) < itg.start_base.get(1) || key.get(2) < itg.start_base.get(2)) |
| 92 | {return true;} |
| 93 | #endif |
| 94 | return false; |
| 95 | } |
| 96 | }; |
| 97 | |
| 98 | template<> |
| 99 | struct launch_insert_sparse_lambda_call<2> |
| 100 | { |
| 101 | template<typename grid_type, typename lambda_t1, typename lambda_t2,typename itd_type, typename coord_type> |
| 102 | __device__ inline static void call(grid_type & grid, |
| 103 | lambda_t1 f1, lambda_t2 f2, |
| 104 | unsigned int blockId, |
| 105 | itd_type itd, |
| 106 | coord_type & key, |
| 107 | coord_type & keyg,unsigned int offset, bool & is_block_empty, |
| 108 | bool is_in) |
| 109 | { |
| 110 | #ifdef __NVCC__ |
| 111 | |
| 112 | bool is_active = false; |
| 113 | if (is_in == true) |
| 114 | {is_active = f1(keyg.get(0),keyg.get(1));} |
| 115 | |
| 116 | if (is_active == true) |
| 117 | {is_block_empty = false;} |
| 118 | |
| 119 | __syncthreads(); |
| 120 | |
| 121 | if (is_block_empty == false) |
| 122 | { |
| 123 | auto ec = grid.insertBlock(blockId); |
| 124 | enc_num<decltype(grid.insertBlock(blockId))> ecn(ec,offset); |
| 125 | |
| 126 | if ( is_active == true) |
| 127 | { |
| 128 | f2(ecn,keyg.get(0),keyg.get(1)); |
| 129 | ec.template get<grid_type::pMask>()[offset] = 1; |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | #endif |
| 134 | } |
| 135 | |
| 136 | template<typename ite_type> |
| 137 | __device__ inline static bool set_keys(grid_key_dx<2,int> & key, grid_key_dx<2,int> & keyg, ite_type & itg) |
| 138 | { |
| 139 | #ifdef __NVCC__ |
| 140 | key.set_d(0,threadIdx.x + blockIdx.x * blockDim.x + itg.start.get(0)); |
| 141 | key.set_d(1,threadIdx.y + blockIdx.y * blockDim.y + itg.start.get(1)); |
| 142 | |
| 143 | keyg.set_d(0,key.get(0) + itg.origin.get(0)); |
| 144 | keyg.set_d(1,key.get(1) + itg.origin.get(1)); |
| 145 | |
| 146 | if (key.get(0) > itg.stop.get(0) || key.get(1) > itg.stop.get(1) || |
| 147 | key.get(0) < itg.start_base.get(0) || key.get(1) < itg.start_base.get(1)) |
| 148 | {return true;} |
| 149 | #endif |
| 150 | return false; |
| 151 | } |
| 152 | }; |
| 153 | |
| 154 | struct launch_insert_sparse |
| 155 | { |
| 156 | template<typename grid_type, typename ite_type, typename lambda_f1, typename lambda_f2> |
| 157 | __device__ void operator()(grid_type & grid, ite_type itg, bool & is_block_empty, lambda_f1 f1, lambda_f2 f2) |
| 158 | { |
| 159 | #ifdef __NVCC__ |
| 160 | |
| 161 | grid_key_dx<grid_type::dims,int> key; |
| 162 | grid_key_dx<grid_type::dims,int> keyg; |
| 163 | |
| 164 | bool not_active = launch_insert_sparse_lambda_call<grid_type::dims>::set_keys(key,keyg,itg); |
| 165 | |
| 166 | if (threadIdx.x == 0 && threadIdx.y == 0 && threadIdx.z == 0) |
| 167 | {is_block_empty = true;} |
| 168 | |
| 169 | grid.init(); |
| 170 | |
| 171 | int offset = 0; |
| 172 | grid_key_dx<grid_type::dims,int> blk; |
| 173 | bool out = grid.template getInsertBlockOffset<ite_type>(itg,key,blk,offset); |
| 174 | |
| 175 | auto blockId = grid.getBlockLinId(blk); |
| 176 | |
| 177 | launch_insert_sparse_lambda_call<grid_type::dims>::call(grid,f1,f2,blockId,itg,key,keyg,offset,is_block_empty,!not_active); |
| 178 | |
| 179 | __syncthreads(); |
| 180 | |
| 181 | grid.flush_block_insert(); |
| 182 | #endif |
| 183 | } |
| 184 | }; |
| 185 | |
| 186 | template<bool is_free> |
| 187 | struct selvg |
| 188 | { |
| 189 | template<typename a_it_type, typename gdb_ext_type, typename gList_type> |
| 190 | static inline void call(a_it_type & a_it, gdb_ext_type & gdb_ext, gList_type & gList, size_t & g_c) |
| 191 | { |
| 192 | if (gdb_ext.get(g_c).Dbox.isValid() == false) |
| 193 | {g_c++;} |
| 194 | else |
| 195 | { |
| 196 | a_it.reinitialize(gList.get(g_c).getIterator(gdb_ext.get(g_c).Dbox.getKP1(),gdb_ext.get(g_c).Dbox.getKP2())); |
| 197 | if (a_it.isNext() == false) {g_c++;} |
| 198 | } |
| 199 | } |
| 200 | }; |
| 201 | |
| 202 | template<> |
| 203 | struct selvg<false> |
| 204 | { |
| 205 | template<typename a_it_type, typename gdb_ext_type, typename gList_type> |
| 206 | static inline void call(a_it_type & a_it, gdb_ext_type & gdb_ext, gList_type & gList, size_t & g_c) |
| 207 | { |
| 208 | // Full iterator (no subset) |
| 209 | a_it.reinitialize(gList.get(g_c).getIterator()); |
| 210 | if (a_it.isNext() == false) {g_c++;} |
| 211 | } |
| 212 | }; |
| 213 | |
| 214 | /*! \brief Distributed grid iterator |
| 215 | * |
| 216 | * Iterator across the local elements of the distributed grid |
| 217 | * |
| 218 | * \tparam dim dimensionality of the grid |
| 219 | * \tparam device_grid type of basic grid |
| 220 | * \tparam stencil it inject the code to calculate stencil offset |
| 221 | * \tparam sub_iterator it indicate the sub-iterator type of the device_grid |
| 222 | * |
| 223 | */ |
| 224 | template<unsigned int dim, typename device_grid, typename device_sub_it, int impl, typename stencil = no_stencil > |
| 225 | class grid_dist_iterator |
| 226 | { |
| 227 | //! grid list counter |
| 228 | size_t g_c; |
| 229 | |
| 230 | //! List of the grids we are going to iterate |
| 231 | const openfpm::vector<device_grid> & gList; |
| 232 | |
| 233 | //! Extension of each grid: domain and ghost + domain |
| 234 | const openfpm::vector<GBoxes<device_grid::dims>> & gdb_ext; |
| 235 | |
| 236 | //! Actual iterator |
| 237 | device_sub_it a_it; |
| 238 | |
| 239 | //! stop point (is the grid size) |
| 240 | grid_key_dx<dim> stop; |
| 241 | |
| 242 | /*! \brief from g_c increment g_c until you find a valid grid |
| 243 | * |
| 244 | */ |
| 245 | void selectValidGrid() |
| 246 | { |
| 247 | do |
| 248 | { |
| 249 | if (impl == FREE) |
| 250 | { |
| 251 | // When the grid has size 0 potentially all the other informations are garbage |
| 252 | while (g_c < gList.size() && (gList.get(g_c).size() == 0 || gdb_ext.get(g_c).Dbox.isValid() == false ) ) g_c++; |
| 253 | } |
| 254 | else |
| 255 | { |
| 256 | // When the grid has size 0 potentially all the other informations are garbage |
| 257 | while (g_c < gList.size() && (gList.get(g_c).size() == 0 || gdb_ext.get(g_c).GDbox.isValid() == false) ) g_c++; |
| 258 | } |
| 259 | |
| 260 | // get the next grid iterator |
| 261 | if (g_c < gList.size()) |
| 262 | { |
| 263 | selvg<impl == FREE>::call(a_it,gdb_ext,gList,g_c); |
| 264 | } |
| 265 | } while (g_c < gList.size() && a_it.isNext() == false); |
| 266 | |
| 267 | } |
| 268 | |
| 269 | public: |
| 270 | |
| 271 | /*! \brief Constructor of the distributed grid iterator |
| 272 | * |
| 273 | * \param gk std::vector of the local grid |
| 274 | * \param gdb_ext set of local subdomains |
| 275 | * \param stop end point |
| 276 | * |
| 277 | */ |
| 278 | grid_dist_iterator(const openfpm::vector<device_grid> & gk, |
| 279 | const openfpm::vector<GBoxes<device_grid::dims>> & gdb_ext, |
| 280 | const grid_key_dx<dim> & stop) |
| 281 | :g_c(0),gList(gk),gdb_ext(gdb_ext),stop(stop) |
| 282 | { |
| 283 | // Initialize the current iterator |
| 284 | // with the first grid |
| 285 | selectValidGrid(); |
| 286 | } |
| 287 | |
| 288 | |
| 289 | /*! \brief Constructor of the distributed grid iterator with |
| 290 | * stencil support |
| 291 | * |
| 292 | * \param gk std::vector of the local grid |
| 293 | * \param gdb_ext set of local subdomains |
| 294 | * \param stop end point |
| 295 | * \param stencil_pnt stencil points |
| 296 | * |
| 297 | */ |
| 298 | grid_dist_iterator(openfpm::vector<device_grid> & gk, |
| 299 | const openfpm::vector<GBoxes<device_grid::dims>> & gdb_ext, |
| 300 | const grid_key_dx<dim> & stop, |
| 301 | const grid_key_dx<dim> (& stencil_pnt)[stencil::nsp]) |
| 302 | :g_c(0),gList(gk),gdb_ext(gdb_ext),a_it(stencil_pnt),stop(stop) |
| 303 | { |
| 304 | // Initialize the current iterator |
| 305 | // with the first grid |
| 306 | selectValidGrid(); |
| 307 | } |
| 308 | |
| 309 | //! Copy constructor |
| 310 | grid_dist_iterator(const grid_dist_iterator<dim,device_grid,device_sub_it,impl,stencil> & g) |
| 311 | :g_c(g.g_c),gList(g.gList),gdb_ext(g.gdb_ext),a_it(g.a_it),stop(g.stop) |
| 312 | {} |
| 313 | |
| 314 | //! Copy constructor |
| 315 | grid_dist_iterator(grid_dist_iterator<dim,device_grid,device_sub_it,impl,stencil> && g) |
| 316 | :g_c(g.g_c),gList(g.gList),gdb_ext(g.gdb_ext),a_it(g.a_it),stop(g.stop) |
| 317 | {} |
| 318 | |
| 319 | //! Destructor |
| 320 | ~grid_dist_iterator() |
| 321 | { |
| 322 | } |
| 323 | |
| 324 | /*! \brief Get the next element |
| 325 | * |
| 326 | * \return the next grid_key |
| 327 | * |
| 328 | */ |
| 329 | inline grid_dist_iterator<dim,device_grid,device_sub_it,impl,stencil> & operator++() |
| 330 | { |
| 331 | ++a_it; |
| 332 | |
| 333 | // check if a_it is at the end |
| 334 | |
| 335 | if (a_it.isNext() == true) |
| 336 | return *this; |
| 337 | else |
| 338 | { |
| 339 | // switch to the new grid |
| 340 | g_c++; |
| 341 | |
| 342 | selectValidGrid(); |
| 343 | } |
| 344 | |
| 345 | return *this; |
| 346 | } |
| 347 | |
| 348 | /*! \brief Check if there is the next element |
| 349 | * |
| 350 | * \return true if there is the next, false otherwise |
| 351 | * |
| 352 | */ |
| 353 | inline bool isNext() const |
| 354 | { |
| 355 | // If there are no other grid stop |
| 356 | |
| 357 | if (g_c >= gList.size()) |
| 358 | {return false;} |
| 359 | |
| 360 | return true; |
| 361 | } |
| 362 | |
| 363 | /*! \brief Get the actual key |
| 364 | * |
| 365 | * \return the actual key |
| 366 | * |
| 367 | */ |
| 368 | inline grid_dist_key_dx<dim, typename device_grid::base_key> get() const |
| 369 | { |
| 370 | return grid_dist_key_dx<dim,typename device_grid::base_key>(g_c,a_it.get()); |
| 371 | } |
| 372 | |
| 373 | /*! \brief it return the stop point of the iterator |
| 374 | * |
| 375 | * The stop point of the iterator is just the grid size |
| 376 | * |
| 377 | * \return the stop point |
| 378 | * |
| 379 | */ |
| 380 | inline grid_key_dx<dim> getStop() const |
| 381 | { |
| 382 | return stop; |
| 383 | } |
| 384 | |
| 385 | /*! \brief it return the start point of the iterator |
| 386 | * |
| 387 | * The start point of the iterator is the point with all coordinates zeros |
| 388 | * |
| 389 | * \return the start point |
| 390 | * |
| 391 | */ |
| 392 | inline grid_key_dx<dim> getStart() const |
| 393 | { |
| 394 | grid_key_dx<dim> start; |
| 395 | |
| 396 | start.zero(); |
| 397 | |
| 398 | return start; |
| 399 | } |
| 400 | |
| 401 | /*! \brief Get the boxes |
| 402 | * |
| 403 | * Get the boxes that define the local grids |
| 404 | * |
| 405 | * \return Vector of local boxes |
| 406 | * |
| 407 | */ |
| 408 | inline const openfpm::vector<GBoxes<device_grid::dims>> & getGBoxes() |
| 409 | { |
| 410 | return gdb_ext; |
| 411 | } |
| 412 | |
| 413 | /*! \brief Convert a g_dist_key_dx into a global key |
| 414 | * |
| 415 | * \see grid_dist_key_dx |
| 416 | * \see grid_dist_iterator |
| 417 | * |
| 418 | * \param k key position in local coordinates |
| 419 | * |
| 420 | * \return the global position in the grid |
| 421 | * |
| 422 | */ |
| 423 | inline grid_key_dx<dim> getGKey(const grid_dist_key_dx<dim,typename device_grid::base_key> & k) |
| 424 | { |
| 425 | // Get the sub-domain id |
| 426 | size_t sub_id = k.getSub(); |
| 427 | |
| 428 | auto k_glob = k.getKey(); |
| 429 | |
| 430 | // shift |
| 431 | auto k_glob2 = k_glob + gdb_ext.get(sub_id).origin; |
| 432 | |
| 433 | return k_glob2; |
| 434 | } |
| 435 | |
| 436 | /*! \brief Return the stencil point offset |
| 437 | * |
| 438 | * \tparam id |
| 439 | * |
| 440 | * \return linearized distributed key |
| 441 | * |
| 442 | */ |
| 443 | template<unsigned int id> inline grid_dist_lin_dx getStencil() |
| 444 | { |
| 445 | return grid_dist_lin_dx(g_c,a_it.template getStencil<id>()); |
| 446 | } |
| 447 | }; |
| 448 | |
| 449 | |
| 450 | |
| 451 | #endif /* GRID_DIST_ID_ITERATOR_SUB_HPP_ */ |
| 452 | |