@@ -7,6 +7,65 @@ namespace amrex {
77// / \cond DOXYGEN_IGNORE
88namespace detail
99{
10+ template <typename F>
11+ AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
12+ void forEachIntersectingTile (IntVect const & iv, int nGrow,
13+ Box const & grid_box, IntVect const & periodic_shift,
14+ bool do_tiling, IntVect const & tile_size, F&& f)
15+ {
16+ Box cell_box (iv, iv);
17+ cell_box.grow (nGrow);
18+ cell_box += periodic_shift;
19+ cell_box &= grid_box;
20+
21+ if (!cell_box.ok ()) { return ; }
22+
23+ auto const & cb_lo = cell_box.smallEnd ();
24+ auto const & cb_hi = cell_box.bigEnd ();
25+
26+ #if (AMREX_SPACEDIM == 1)
27+ for (int i = cb_lo[0 ]; i <= cb_hi[0 ]; ++i) {
28+ IntVect cell (AMREX_D_DECL (i, 0 , 0 ));
29+ Box tbx;
30+ int tile = getTileIndex (cell, grid_box, do_tiling, tile_size, tbx);
31+ IntVect rep (AMREX_D_DECL (amrex::max (cb_lo[0 ], tbx.smallEnd (0 )), 0 , 0 ));
32+ if (cell == rep) {
33+ f (tile);
34+ }
35+ }
36+ #elif (AMREX_SPACEDIM == 2)
37+ for (int j = cb_lo[1 ]; j <= cb_hi[1 ]; ++j) {
38+ for (int i = cb_lo[0 ]; i <= cb_hi[0 ]; ++i) {
39+ IntVect cell (AMREX_D_DECL (i, j, 0 ));
40+ Box tbx;
41+ int tile = getTileIndex (cell, grid_box, do_tiling, tile_size, tbx);
42+ IntVect rep (AMREX_D_DECL (amrex::max (cb_lo[0 ], tbx.smallEnd (0 )),
43+ amrex::max (cb_lo[1 ], tbx.smallEnd (1 )),
44+ 0 ));
45+ if (cell == rep) {
46+ f (tile);
47+ }
48+ }
49+ }
50+ #else
51+ for (int k = cb_lo[2 ]; k <= cb_hi[2 ]; ++k) {
52+ for (int j = cb_lo[1 ]; j <= cb_hi[1 ]; ++j) {
53+ for (int i = cb_lo[0 ]; i <= cb_hi[0 ]; ++i) {
54+ IntVect cell (AMREX_D_DECL (i, j, k));
55+ Box tbx;
56+ int tile = getTileIndex (cell, grid_box, do_tiling, tile_size, tbx);
57+ IntVect rep (AMREX_D_DECL (amrex::max (cb_lo[0 ], tbx.smallEnd (0 )),
58+ amrex::max (cb_lo[1 ], tbx.smallEnd (1 )),
59+ amrex::max (cb_lo[2 ], tbx.smallEnd (2 ))));
60+ if (cell == rep) {
61+ f (tile);
62+ }
63+ }
64+ }
65+ }
66+ #endif
67+ }
68+
1069 inline Vector<Box> getBoundaryBoxes (const Box& box, int ncells)
1170 {
1271 AMREX_ASSERT_WITH_MESSAGE (box.size () > 2 *IntVect (AMREX_D_DECL (ncells, ncells, ncells)),
@@ -86,7 +145,6 @@ buildNeighborMask ()
86145 {
87146 int nbor_grid = isec.first ;
88147 const Box isec_box = isec.second - pshift;
89- if ( (grid == nbor_grid) && (pshift == 0 )) { continue ; }
90148 neighbor_grids.insert (NeighborTask (nbor_grid, isec_box, pshift));
91149 const int global_rank = dmap[nbor_grid];
92150 neighbor_procs.push_back (ParallelContext::global_to_local_rank (global_rank));
@@ -173,7 +231,7 @@ buildNeighborCopyOp (bool use_boundary_neighbor)
173231 const int nisec_box = m_isec_boxes[gid].size ();
174232 const bool do_tiling = this ->do_tiling ;
175233 const IntVect tile_size = this ->tile_size ;
176- // auto p_code_offsets = m_code_offsets[gid].dataPtr() ;
234+ const int nGrow = m_num_neighbor_cells ;
177235
178236 AMREX_FOR_1D ( np, i,
179237 {
@@ -186,7 +244,20 @@ buildNeighborCopyOp (bool use_boundary_neighbor)
186244 IntVect iv = getParticleCell (p_ptr[pid], plo, dxi, domain);
187245 for (int j=0 ; j<nisec_box; ++j) {
188246 if (p_isec_boxes[j].contains (iv)) {
189- ++p_counts[i];
247+ detail::forEachIntersectingTile (iv, nGrow,
248+ p_code_array[j].grid_box ,
249+ p_code_array[j].periodic_shift ,
250+ do_tiling, tile_size,
251+ [&] (int dst_tile)
252+ {
253+ bool is_self = (p_code_array[j].grid_id == gid) && (dst_tile == tid)
254+ AMREX_D_TERM ( && (p_code_array[j].periodic_shift [0 ] == 0 ),
255+ && (p_code_array[j].periodic_shift [1 ] == 0 ),
256+ && (p_code_array[j].periodic_shift [2 ] == 0 ));
257+ if (!is_self) {
258+ ++p_counts[i];
259+ }
260+ });
190261 }
191262 }
192263 });
@@ -217,14 +288,25 @@ buildNeighborCopyOp (bool use_boundary_neighbor)
217288 int k = p_offsets[i];
218289 for (int j=0 ; j<nisec_box; ++j) {
219290 if (p_isec_boxes[j].contains (iv)) {
220- p_boxes[k] = p_code_array[j].grid_id ;
221- Box tbx;
222- p_tiles[k] = getTileIndex (iv, p_code_array[j].grid_box ,
223- do_tiling, tile_size, tbx);
224- p_levs[k] = 0 ;
225- p_periodic_shift[k] = p_code_array[j].periodic_shift ;
226- p_src_indices[k] = pid;
227- ++k;
291+ detail::forEachIntersectingTile (iv, nGrow,
292+ p_code_array[j].grid_box ,
293+ p_code_array[j].periodic_shift ,
294+ do_tiling, tile_size,
295+ [&] (int dst_tile)
296+ {
297+ bool is_self = (p_code_array[j].grid_id == gid) && (dst_tile == tid)
298+ AMREX_D_TERM ( && (p_code_array[j].periodic_shift [0 ] == 0 ),
299+ && (p_code_array[j].periodic_shift [1 ] == 0 ),
300+ && (p_code_array[j].periodic_shift [2 ] == 0 ));
301+ if (!is_self) {
302+ p_boxes[k] = p_code_array[j].grid_id ;
303+ p_tiles[k] = dst_tile;
304+ p_levs[k] = 0 ;
305+ p_periodic_shift[k] = p_code_array[j].periodic_shift ;
306+ p_src_indices[k] = pid;
307+ ++k;
308+ }
309+ });
228310 }
229311 }
230312 AMREX_ALWAYS_ASSERT (k == p_offsets[i+1 ]);
@@ -243,9 +325,6 @@ fillNeighborsGPU ()
243325
244326 AMREX_ASSERT (numParticlesOutOfRange (*this , 0 ) == 0 );
245327
246- AMREX_ALWAYS_ASSERT_WITH_MESSAGE (this ->do_tiling == 0 ,
247- " Tiling on the GPU is not supported for neighbor particles." );
248-
249328 buildNeighborMask ();
250329 this ->defineBufferMap ();
251330
0 commit comments