Cabana 0.8.0-dev
 
Loading...
Searching...
No Matches
Cabana_VerletList.hpp
Go to the documentation of this file.
1/****************************************************************************
2 * Copyright (c) 2018-2023 by the Cabana authors *
3 * All rights reserved. *
4 * *
5 * This file is part of the Cabana library. Cabana is distributed under a *
6 * BSD 3-clause license. For the licensing terms see the LICENSE file in *
7 * the top-level directory. *
8 * *
9 * SPDX-License-Identifier: BSD-3-Clause *
10 ****************************************************************************/
11
16#ifndef CABANA_VERLETLIST_HPP
17#define CABANA_VERLETLIST_HPP
18
21#include <Cabana_Parallel.hpp>
22
23#include <Kokkos_Core.hpp>
24#include <Kokkos_Profiling_ScopedRegion.hpp>
25
26#include <cassert>
27
28namespace Cabana
29{
30//---------------------------------------------------------------------------//
31// Verlet List Memory Layout Tag.
32//---------------------------------------------------------------------------//
35{
36};
37
40{
41};
42
43//---------------------------------------------------------------------------//
44// Verlet List Data.
45//---------------------------------------------------------------------------//
46template <class MemorySpace, class LayoutTag>
48
50template <class MemorySpace>
51struct VerletListData<MemorySpace, VerletLayoutCSR>
52{
54 using memory_space = MemorySpace;
55
57 Kokkos::View<int*, memory_space> counts;
58
60 Kokkos::View<int*, memory_space> offsets;
61
63 Kokkos::View<int*, memory_space> neighbors;
64
66 KOKKOS_INLINE_FUNCTION
67 void addNeighbor( const int pid, const int nid ) const
68 {
69 neighbors( offsets( pid ) +
70 Kokkos::atomic_fetch_add( &counts( pid ), 1 ) ) = nid;
71 }
72
74 KOKKOS_INLINE_FUNCTION
75 void setNeighbor( const int pid, const int nid, const int new_id ) const
76 {
77 neighbors( offsets( pid ) + nid ) = new_id;
78 }
79};
80
82template <class MemorySpace>
83struct VerletListData<MemorySpace, VerletLayout2D>
84{
86 using memory_space = MemorySpace;
87
89 Kokkos::View<int*, memory_space> counts;
90
92 Kokkos::View<int**, memory_space> neighbors;
93
96 std::size_t max_n;
97
99 KOKKOS_INLINE_FUNCTION
100 void addNeighbor( const int pid, const int nid ) const
101 {
102 std::size_t count = Kokkos::atomic_fetch_add( &counts( pid ), 1 );
103 if ( count < neighbors.extent( 1 ) )
104 neighbors( pid, count ) = nid;
105 }
106
108 KOKKOS_INLINE_FUNCTION
109 void setNeighbor( const int pid, const int nid, const int new_id ) const
110 {
111 neighbors( pid, nid ) = new_id;
112 }
113};
114
115//---------------------------------------------------------------------------//
116
117//---------------------------------------------------------------------------//
118
119namespace Impl
120{
122
123//---------------------------------------------------------------------------//
124// Verlet List Builder
125//---------------------------------------------------------------------------//
126template <class DeviceType, class RandomAccessPositionType, class RadiusType,
127 class AlgorithmTag, class LayoutTag, class BuildOpTag,
128 class ArrayType, std::size_t NumSpaceDim>
129struct VerletListBuilder
130{
131 static constexpr std::size_t num_space_dim = NumSpaceDim;
132
133 // Types.
134 using device = DeviceType;
135 using PositionValueType = typename RandomAccessPositionType::value_type;
136 using memory_space = typename device::memory_space;
137 using execution_space = typename device::execution_space;
138
139 // List data.
140 VerletListData<memory_space, LayoutTag> _data;
141 // Background squared neighbor cutoff.
142 PositionValueType rsqr;
143 // Fixed or per-particle neighbor radius.
144 RadiusType radius;
145
146 // Positions.
147 RandomAccessPositionType _position;
148 std::size_t pid_begin, pid_end;
149
150 // Binning Data.
151 BinningData<memory_space> bin_data_1d;
152 LinkedCellList<memory_space, PositionValueType, num_space_dim>
153 linked_cell_list;
154
155 // Check to count or refill.
156 bool refill;
157 bool count;
158
159 // Maximum allocated neighbors per particle
160 std::size_t alloc_n;
161
162 // Constructor with a single cutoff radius.
163 template <class PositionType>
164 VerletListBuilder( PositionType positions, const std::size_t begin,
165 const std::size_t end,
166 const RadiusType neighborhood_radius,
167 const PositionValueType cell_size_ratio,
168 const ArrayType grid_min, const ArrayType grid_max,
169 const std::size_t max_neigh )
170 : pid_begin( begin )
171 , pid_end( end )
172 , alloc_n( max_neigh )
173 {
174 init( positions, neighborhood_radius, cell_size_ratio, grid_min,
175 grid_max );
176 // This value is not currently used, but set to be consistent with the
177 // variable cutoff case below.
178 radius = neighborhood_radius;
179 }
180
181 // Constructor with a background radius (used for the LinkedCellList) and a
182 // per-particle radius.
183 template <class PositionType>
184 VerletListBuilder( PositionType positions, const std::size_t begin,
185 const std::size_t end,
186 const PositionValueType background_radius,
187 const RadiusType neighborhood_radius,
188 const PositionValueType cell_size_ratio,
189 const ArrayType grid_min, const ArrayType grid_max,
190 const std::size_t max_neigh )
191 : pid_begin( begin )
192 , pid_end( end )
193 , alloc_n( max_neigh )
194 {
195 assert( size( positions ) == size( neighborhood_radius ) );
196 init( positions, background_radius, cell_size_ratio, grid_min,
197 grid_max );
198
199 // Store a shallow copy (not squared).
200 // TODO: for cases where the radii never change, this could be better
201 // optimized with a deep copy of the squared radius instead.
202 radius = neighborhood_radius;
203 }
204
205 template <class PositionType>
206 void init( PositionType positions,
207 const PositionValueType neighborhood_radius,
208 const PositionValueType cell_size_ratio,
209 const ArrayType grid_min, const ArrayType grid_max )
210 {
211 count = true;
212 refill = false;
213
214 // Create the count view.
215 _data.counts = Kokkos::View<int*, memory_space>( "num_neighbors",
216 size( positions ) );
217
218 // Make a guess for the number of neighbors per particle for 2D lists.
219 initCounts( LayoutTag() );
220
221 // Shallow copy for random access read-only memory.
222 _position = positions;
223
224 double grid_size = cell_size_ratio * neighborhood_radius;
225 ArrayType grid_delta;
226 for ( std::size_t d = 0; d < num_space_dim; ++d )
227 grid_delta[d] = grid_size;
228
229 // Bin the particles in the grid. Don't actually sort them but make a
230 // permutation vector. Note that we are binning all particles here and
231 // not just the requested range. This is because all particles are
232 // treated as candidates for neighbors.
233 linked_cell_list =
234 createLinkedCellList( _position, grid_delta, grid_min, grid_max,
235 neighborhood_radius, cell_size_ratio );
236 bin_data_1d = linked_cell_list.binningData();
237
238 // We will use the square of the distance for neighbor determination.
239 rsqr = neighborhood_radius * neighborhood_radius;
240 }
241
242 // Check if particle pair i-j is within cutoff, potentially with variable
243 // radii.
244 KOKKOS_INLINE_FUNCTION auto withinCutoff( [[maybe_unused]] const int i,
245 const double dist_sqr ) const
246 {
247 // Square the radius on the fly if using a per-particle field to avoid a
248 // deep copy.
249 if constexpr ( is_slice<RadiusType>::value ||
250 Kokkos::is_view<RadiusType>::value )
251 return dist_sqr <= radius( i ) * radius( i );
252 // This value is already squared.
253 else
254 return dist_sqr <= rsqr;
255 }
256
257 // Check if potential neighbor j is NOT within cutoff, meaning particle i
258 // should add instead for symmetry.
259 KOKKOS_INLINE_FUNCTION auto
260 neighborNotWithinCutoff( [[maybe_unused]] const int j,
261 [[maybe_unused]] const double dist_sqr ) const
262 {
263 // This neighbor needs to be added if they will not find this particle.
264 if constexpr ( is_slice<RadiusType>::value ||
265 Kokkos::is_view<RadiusType>::value )
266 {
267 return dist_sqr >= radius( j ) * radius( j );
268 }
269 else
270 {
271 // For a fixed radius, this will never occur.
272 return false;
273 }
274 }
275
276 // Count neighbors, with consideration for self particle i and neighbor j.
277 KOKKOS_INLINE_FUNCTION auto countNeighbor( const int i, const int j,
278 const double dist_sqr ) const
279 {
280 int c = 0;
281 // Always add self if within cutoff.
282 if ( withinCutoff( i, dist_sqr ) )
283 {
284 c++;
285 // Add neighbor if they will not find this particle.
286 if ( neighborNotWithinCutoff( j, dist_sqr ) )
287 c++;
288 }
289 return c;
290 }
291
292 // Add neighbors, with consideration for self particle i and neighbor j.
293 KOKKOS_INLINE_FUNCTION void addNeighbor( const int i, const int j,
294 const double dist_sqr ) const
295 {
296 // Always add self if within cutoff.
297 if ( withinCutoff( i, dist_sqr ) )
298 {
299 _data.addNeighbor( i, j );
300
301 // Add neighbor if they will not find this particle.
302 if ( neighborNotWithinCutoff( j, dist_sqr ) )
303 _data.addNeighbor( j, i );
304 }
305 }
306
307 // Neighbor count team operator (only used for CSR lists).
308 struct CountNeighborsTag
309 {
310 };
311 using CountNeighborsPolicy =
312 Kokkos::TeamPolicy<execution_space, CountNeighborsTag,
313 Kokkos::IndexType<int>,
314 Kokkos::Schedule<Kokkos::Dynamic>>;
315
316 KOKKOS_INLINE_FUNCTION
317 void
318 operator()( const CountNeighborsTag&,
319 const typename CountNeighborsPolicy::member_type& team ) const
320 {
321 // The league rank of the team is the cardinal cell index we are
322 // working on.
323 int cell = team.league_rank();
324
325 // Get the stencil for this cell.
326 Kokkos::Array<int, num_space_dim> min;
327 Kokkos::Array<int, num_space_dim> max;
328 linked_cell_list.getStencilCells( cell, min, max );
329
330 // Operate on the particles in the bin.
331 std::size_t b_offset = bin_data_1d.binOffset( cell );
332 Kokkos::parallel_for(
333 Kokkos::TeamThreadRange( team, 0, bin_data_1d.binSize( cell ) ),
334 [&]( const int bi )
335 {
336 // Get the true particle id. The binned particle index is the
337 // league rank of the team.
338 std::size_t pid = linked_cell_list.permutation( bi + b_offset );
339
340 if ( ( pid >= pid_begin ) && ( pid < pid_end ) )
341 {
342 // Cache the particle coordinates.
343 Kokkos::Array<PositionValueType, num_space_dim> xp;
344 for ( std::size_t d = 0; d < num_space_dim; ++d )
345 xp[d] = _position( pid, d );
346
347 // Loop over the cell stencil.
348 int stencil_count =
349 linkedcell_stencil_count( team, min, max, xp, pid );
350
351 Kokkos::single( Kokkos::PerThread( team ), [&]()
352 { _data.counts( pid ) = stencil_count; } );
353 }
354 } );
355 }
356
357 template <class TeamType, std::size_t NSD = num_space_dim>
358 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, int>
359 linkedcell_stencil_count( TeamType team, const Kokkos::Array<int, 3> min,
360 const Kokkos::Array<int, 3> max,
361 const Kokkos::Array<PositionValueType, 3> xp,
362 const std::size_t pid ) const
363 {
364 int stencil_count = 0;
365 Kokkos::Array<int, 3> ijk;
366 for ( int i = min[0]; i < max[0]; ++i )
367 for ( int j = min[1]; j < max[1]; ++j )
368 for ( int k = min[2]; k < max[2]; ++k )
369 {
370 ijk = { i, j, k };
371 linkedcell_bin( team, ijk, xp, pid, stencil_count );
372 }
373 return stencil_count;
374 }
375
376 template <class TeamType, std::size_t NSD = num_space_dim>
377 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, int>
378 linkedcell_stencil_count( TeamType team, const Kokkos::Array<int, 2> min,
379 const Kokkos::Array<int, 2> max,
380 const Kokkos::Array<PositionValueType, 2> xp,
381 const std::size_t pid ) const
382 {
383 int stencil_count = 0;
384 Kokkos::Array<int, 2> ij;
385 for ( int i = min[0]; i < max[0]; ++i )
386 for ( int j = min[1]; j < max[1]; ++j )
387 {
388 ij = { i, j };
389 linkedcell_bin( team, ij, xp, pid, stencil_count );
390 }
391 return stencil_count;
392 }
393
394 template <class TeamType>
395 KOKKOS_INLINE_FUNCTION void
396 linkedcell_bin( TeamType team, const Kokkos::Array<int, num_space_dim> ijk,
397 const Kokkos::Array<PositionValueType, num_space_dim> xp,
398 const std::size_t pid, int& stencil_count ) const
399 {
400 // See if we should actually check this box for neighbors.
401 if ( withinCutoff(
402 pid, linked_cell_list.cellStencil().grid.minDistanceToPoint(
403 xp, ijk ) ) )
404 {
405 std::size_t n_offset = linked_cell_list.binOffset( ijk );
406 std::size_t num_n = linked_cell_list.binSize( ijk );
407
408 // Check the particles in this bin to see if they are neighbors. If
409 // they are add to the count for this bin.
410 int cell_count = 0;
411 neighbor_reduce( team, pid, xp, n_offset, num_n, cell_count,
412 BuildOpTag() );
413 stencil_count += cell_count;
414 }
415 }
416
417 // Neighbor count team vector loop (only used for CSR lists).
418 KOKKOS_INLINE_FUNCTION void
419 neighbor_reduce( const typename CountNeighborsPolicy::member_type& team,
420 const std::size_t pid,
421 const Kokkos::Array<double, num_space_dim> xp,
422 const int n_offset, const int num_n, int& cell_count,
423 TeamVectorOpTag ) const
424 {
425 Kokkos::parallel_reduce(
426 Kokkos::ThreadVectorRange( team, num_n ),
427 [&]( const int n, int& local_count )
428 { neighbor_kernel( pid, xp, n_offset, n, local_count ); },
429 cell_count );
430 }
431
432 // Neighbor count serial loop (only used for CSR lists).
433 KOKKOS_INLINE_FUNCTION
434 void neighbor_reduce( const typename CountNeighborsPolicy::member_type,
435 const std::size_t pid,
436 const Kokkos::Array<double, num_space_dim> xp,
437 const int n_offset, const int num_n, int& cell_count,
438 TeamOpTag ) const
439 {
440 for ( int n = 0; n < num_n; n++ )
441 neighbor_kernel( pid, xp, n_offset, n, cell_count );
442 }
443
444 // Neighbor count kernel
445 KOKKOS_INLINE_FUNCTION
446 void neighbor_kernel( const int pid,
447 const Kokkos::Array<double, num_space_dim> xp,
448 const int n_offset, const int n,
449 int& local_count ) const
450 {
451 // Get the true id of the candidate neighbor.
452 std::size_t nid = linked_cell_list.permutation( n_offset + n );
453
454 // Cache the candidate neighbor particle coordinates.
455 Kokkos::Array<double, num_space_dim> xn;
456 for ( std::size_t d = 0; d < num_space_dim; ++d )
457 xn[d] = _position( nid, d );
458
459 // If this could be a valid neighbor, continue.
460 if ( NeighborDiscriminator<AlgorithmTag>::isValid( pid, xp, nid, xn ) )
461 {
462 // Calculate the distance between the particle and its candidate
463 // neighbor.
464 PositionValueType dist_sqr = 0.0;
465 for ( std::size_t d = 0; d < num_space_dim; ++d )
466 {
467 PositionValueType dx = xp[d] - xn[d];
468 dist_sqr += dx * dx;
469 }
470
471 // If within the cutoff add to the count.
472 local_count += countNeighbor( pid, nid, dist_sqr );
473 }
474 }
475
476 // Process the CSR counts by computing offsets and allocating the neighbor
477 // list.
478 template <class KokkosMemorySpace>
479 struct OffsetScanOp
480 {
481 using kokkos_mem_space = KokkosMemorySpace;
482 Kokkos::View<int*, kokkos_mem_space> counts;
483 Kokkos::View<int*, kokkos_mem_space> offsets;
484 KOKKOS_INLINE_FUNCTION
485 void operator()( const int i, int& update, const bool final_pass ) const
486 {
487 if ( final_pass )
488 offsets( i ) = update;
489 update += counts( i );
490 }
491 };
492
493 void initCounts( VerletLayoutCSR ) {}
494
495 void initCounts( VerletLayout2D )
496 {
497 if ( alloc_n > 0 )
498 {
499 count = false;
500
501 _data.neighbors = Kokkos::View<int**, memory_space>(
502 Kokkos::ViewAllocateWithoutInitializing( "neighbors" ),
503 _data.counts.size(), alloc_n );
504 }
505 }
506
507 void processCounts( VerletLayoutCSR )
508 {
509 // Allocate offsets.
510 _data.offsets = Kokkos::View<int*, memory_space>(
511 Kokkos::ViewAllocateWithoutInitializing( "neighbor_offsets" ),
512 _data.counts.size() );
513
514 // Calculate offsets from counts and the total number of counts.
515 OffsetScanOp<memory_space> offset_op;
516 offset_op.counts = _data.counts;
517 offset_op.offsets = _data.offsets;
518 int total_num_neighbor;
519 Kokkos::RangePolicy<execution_space> range_policy(
520 0, _data.counts.extent( 0 ) );
521 Kokkos::parallel_scan( "Cabana::VerletListBuilder::offset_scan",
522 range_policy, offset_op, total_num_neighbor );
523 Kokkos::fence();
524
525 // Allocate the neighbor list.
526 _data.neighbors = Kokkos::View<int*, memory_space>(
527 Kokkos::ViewAllocateWithoutInitializing( "neighbors" ),
528 total_num_neighbor );
529
530 // Reset the counts. We count again when we fill.
531 Kokkos::deep_copy( _data.counts, 0 );
532 }
533
534 // Process 2D counts by computing the maximum number of neighbors and
535 // reallocating the 2D data structure if needed.
536 void processCounts( VerletLayout2D )
537 {
538 // Calculate the maximum number of neighbors.
539 auto counts = _data.counts;
540 int max;
541 Kokkos::Max<int> max_reduce( max );
542 Kokkos::parallel_reduce(
543 "Cabana::VerletListBuilder::reduce_max",
544 Kokkos::RangePolicy<execution_space>( 0, _data.counts.size() ),
545 KOKKOS_LAMBDA( const int i, int& value ) {
546 if ( counts( i ) > value )
547 value = counts( i );
548 },
549 max_reduce );
550 Kokkos::fence();
551 _data.max_n = static_cast<std::size_t>( max );
552
553 // Reallocate the neighbor list if previous size is exceeded.
554 if ( count or _data.max_n > _data.neighbors.extent( 1 ) )
555 {
556 refill = true;
557 Kokkos::deep_copy( _data.counts, 0 );
558 _data.neighbors = Kokkos::View<int**, memory_space>(
559 Kokkos::ViewAllocateWithoutInitializing( "neighbors" ),
560 _data.counts.size(), _data.max_n );
561 }
562 }
563
564 // Neighbor count team operator.
565 struct FillNeighborsTag
566 {
567 };
568 using FillNeighborsPolicy =
569 Kokkos::TeamPolicy<execution_space, FillNeighborsTag,
570 Kokkos::IndexType<int>,
571 Kokkos::Schedule<Kokkos::Dynamic>>;
572 KOKKOS_INLINE_FUNCTION
573 void
574 operator()( const FillNeighborsTag&,
575 const typename FillNeighborsPolicy::member_type& team ) const
576 {
577 // The league rank of the team is the cardinal cell index we are
578 // working on.
579 int cell = team.league_rank();
580
581 // Get the stencil for this cell.
582 Kokkos::Array<int, num_space_dim> min;
583 Kokkos::Array<int, num_space_dim> max;
584 linked_cell_list.getStencilCells( cell, min, max );
585
586 // Operate on the particles in the bin.
587 std::size_t b_offset = bin_data_1d.binOffset( cell );
588 Kokkos::parallel_for(
589 Kokkos::TeamThreadRange( team, 0, bin_data_1d.binSize( cell ) ),
590 [&]( const int bi )
591 {
592 // Get the true particle id. The binned particle index is the
593 // league rank of the team.
594 std::size_t pid = linked_cell_list.permutation( bi + b_offset );
595
596 if ( ( pid >= pid_begin ) && ( pid < pid_end ) )
597 {
598 // Cache the particle coordinates.
599 Kokkos::Array<PositionValueType, num_space_dim> xp;
600 for ( std::size_t d = 0; d < num_space_dim; ++d )
601 xp[d] = _position( pid, d );
602
603 linkedcell_stencil_fill( team, min, max, xp, pid );
604 }
605 } );
606 }
607
608 template <class TeamType, std::size_t NSD = num_space_dim>
609 KOKKOS_INLINE_FUNCTION std::enable_if_t<3 == NSD, void>
610 linkedcell_stencil_fill( TeamType team, const Kokkos::Array<int, 3> min,
611 const Kokkos::Array<int, 3> max,
612 const Kokkos::Array<PositionValueType, 3> xp,
613 const std::size_t pid ) const
614 {
615 Kokkos::Array<int, 3> ijk;
616 for ( int i = min[0]; i < max[0]; ++i )
617 for ( int j = min[1]; j < max[1]; ++j )
618 for ( int k = min[2]; k < max[2]; ++k )
619 {
620 ijk = { i, j, k };
621 linkedcell_bin( team, ijk, xp, pid );
622 }
623 }
624
625 template <class TeamType, std::size_t NSD = num_space_dim>
626 KOKKOS_INLINE_FUNCTION std::enable_if_t<2 == NSD, void>
627 linkedcell_stencil_fill( TeamType team, const Kokkos::Array<int, 2> min,
628 const Kokkos::Array<int, 2> max,
629 const Kokkos::Array<PositionValueType, 2> xp,
630 const std::size_t pid ) const
631 {
632 Kokkos::Array<int, 2> ij;
633 for ( int i = min[0]; i < max[0]; ++i )
634 for ( int j = min[1]; j < max[1]; ++j )
635 {
636 ij = { i, j };
637 linkedcell_bin( team, ij, xp, pid );
638 }
639 }
640
641 template <class TeamType>
642 KOKKOS_INLINE_FUNCTION void
643 linkedcell_bin( TeamType team, const Kokkos::Array<int, num_space_dim> ijk,
644 const Kokkos::Array<PositionValueType, num_space_dim> xp,
645 const std::size_t pid ) const
646 {
647 // See if we should actually check this box for neighbors.
648 if ( withinCutoff(
649 pid, linked_cell_list.cellStencil().grid.minDistanceToPoint(
650 xp, ijk ) ) )
651 {
652 // Check the particles in this bin to see if they are neighbors.
653 std::size_t n_offset = linked_cell_list.binOffset( ijk );
654 int num_n = linked_cell_list.binSize( ijk );
655 neighbor_for( team, pid, xp, n_offset, num_n, BuildOpTag() );
656 }
657 }
658
659 // Neighbor fill team vector loop.
660 KOKKOS_INLINE_FUNCTION void
661 neighbor_for( const typename FillNeighborsPolicy::member_type& team,
662 const std::size_t pid,
663 const Kokkos::Array<double, num_space_dim> xp,
664 const int n_offset, const int num_n, TeamVectorOpTag ) const
665 {
666 Kokkos::parallel_for( Kokkos::ThreadVectorRange( team, num_n ),
667 [&]( const int n )
668 { neighbor_kernel( pid, xp, n_offset, n ); } );
669 }
670
671 // Neighbor fill serial loop.
672 KOKKOS_INLINE_FUNCTION
673 void neighbor_for( const typename FillNeighborsPolicy::member_type team,
674 const std::size_t pid,
675 const Kokkos::Array<double, num_space_dim> xp,
676 const int n_offset, const int num_n, TeamOpTag ) const
677 {
678 for ( int n = 0; n < num_n; n++ )
679 Kokkos::single( Kokkos::PerThread( team ), [&]()
680 { neighbor_kernel( pid, xp, n_offset, n ); } );
681 }
682
683 // Neighbor fill kernel.
684 KOKKOS_INLINE_FUNCTION
685 void neighbor_kernel( const int pid,
686 const Kokkos::Array<double, num_space_dim> xp,
687 const int n_offset, const int n ) const
688 {
689 // Get the true id of the candidate neighbor.
690 std::size_t nid = linked_cell_list.permutation( n_offset + n );
691
692 // Cache the candidate neighbor particle coordinates.
693 Kokkos::Array<double, num_space_dim> xn;
694 for ( std::size_t d = 0; d < num_space_dim; ++d )
695 xn[d] = _position( nid, d );
696
697 // If this could be a valid neighbor, continue.
698 if ( NeighborDiscriminator<AlgorithmTag>::isValid( pid, xp, nid, xn ) )
699 {
700 // Calculate the distance between the particle and its candidate
701 // neighbor.
702 PositionValueType dist_sqr = 0.0;
703 for ( std::size_t d = 0; d < num_space_dim; ++d )
704 {
705 PositionValueType dx = xp[d] - xn[d];
706 dist_sqr += dx * dx;
707 }
708
709 // If within the cutoff increment the neighbor count and add as a
710 // neighbor at that index.
711 addNeighbor( pid, nid, dist_sqr );
712 }
713 }
714};
715
716// Builder creation functions. This is only necessary to define the different
717// random access types.
718template <std::size_t NumSpaceDim, class DeviceType, class AlgorithmTag,
719 class LayoutTag, class BuildOpTag, class ArrayType,
720 class PositionType>
721auto createVerletListBuilder(
722 PositionType x, const std::size_t begin, const std::size_t end,
723 const typename PositionType::value_type radius,
724 const typename PositionType::value_type cell_size_ratio,
725 const ArrayType grid_min, const ArrayType grid_max,
726 const std::size_t max_neigh,
727 typename std::enable_if<( is_slice<PositionType>::value ), int>::type* = 0 )
728{
729 using RandomAccessPositionType = typename PositionType::random_access_slice;
730 return VerletListBuilder<DeviceType, RandomAccessPositionType,
731 typename PositionType::value_type, AlgorithmTag,
732 LayoutTag, BuildOpTag, ArrayType, NumSpaceDim>(
733 x, begin, end, radius, cell_size_ratio, grid_min, grid_max, max_neigh );
734}
735
736template <std::size_t NumSpaceDim, class DeviceType, class AlgorithmTag,
737 class LayoutTag, class BuildOpTag, class ArrayType,
738 class PositionType>
739auto createVerletListBuilder(
740 PositionType x, const std::size_t begin, const std::size_t end,
741 const typename PositionType::value_type radius,
742 const typename PositionType::value_type cell_size_ratio,
743 const ArrayType grid_min, const ArrayType grid_max,
744 const std::size_t max_neigh,
745 typename std::enable_if<( Kokkos::is_view<PositionType>::value ),
746 int>::type* = 0 )
747{
748 using memory_space = typename DeviceType::memory_space;
749 using RandomAccessPositionType =
750 Kokkos::View<typename PositionType::data_type, memory_space,
751 Kokkos::MemoryTraits<Kokkos::RandomAccess>>;
752 return VerletListBuilder<DeviceType, RandomAccessPositionType,
753 typename PositionType::value_type, AlgorithmTag,
754 LayoutTag, BuildOpTag, ArrayType, NumSpaceDim>(
755 x, begin, end, radius, cell_size_ratio, grid_min, grid_max, max_neigh );
756}
757
758template <std::size_t NumSpaceDim, class DeviceType, class AlgorithmTag,
759 class LayoutTag, class BuildOpTag, class PositionType,
760 class RadiusType, class ArrayType>
761auto createVerletListBuilder(
762 PositionType x, const std::size_t begin, const std::size_t end,
763 const typename PositionType::value_type background_radius,
764 const RadiusType radius,
765 const typename PositionType::value_type cell_size_ratio,
766 const ArrayType grid_min, const ArrayType grid_max,
767 const std::size_t max_neigh,
768 typename std::enable_if<( is_slice<PositionType>::value ), int>::type* = 0 )
769{
770 using RandomAccessPositionType = typename PositionType::random_access_slice;
771 return VerletListBuilder<DeviceType, RandomAccessPositionType, RadiusType,
772 AlgorithmTag, LayoutTag, BuildOpTag, ArrayType,
773 NumSpaceDim>( x, begin, end, background_radius,
774 radius, cell_size_ratio, grid_min,
775 grid_max, max_neigh );
776}
777
778template <std::size_t NumSpaceDim, class DeviceType, class AlgorithmTag,
779 class LayoutTag, class BuildOpTag, class PositionType,
780 class RadiusType, class ArrayType>
781auto createVerletListBuilder(
782 PositionType x, const std::size_t begin, const std::size_t end,
783 const typename PositionType::value_type background_radius,
784 const RadiusType radius,
785 const typename PositionType::value_type cell_size_ratio,
786 const ArrayType grid_min, const ArrayType grid_max,
787 const std::size_t max_neigh,
788 typename std::enable_if<( Kokkos::is_view<PositionType>::value ),
789 int>::type* = 0 )
790{
791 using RandomAccessPositionType =
792 Kokkos::View<typename PositionType::value_type**, DeviceType,
793 Kokkos::MemoryTraits<Kokkos::RandomAccess>>;
794 return VerletListBuilder<DeviceType, RandomAccessPositionType, RadiusType,
795 AlgorithmTag, LayoutTag, BuildOpTag, ArrayType,
796 NumSpaceDim>( x, begin, end, background_radius,
797 radius, cell_size_ratio, grid_min,
798 grid_max, max_neigh );
799}
800
801//---------------------------------------------------------------------------//
802
804} // end namespace Impl
805
806//---------------------------------------------------------------------------//
824template <class MemorySpace, class AlgorithmTag, class LayoutTag,
825 class BuildTag = TeamVectorOpTag, std::size_t NumSpaceDim = 3>
827{
828 public:
829 static_assert( Kokkos::is_memory_space<MemorySpace>::value, "" );
830
832 static constexpr std::size_t num_space_dim = NumSpaceDim;
833
835 using memory_space = MemorySpace;
836
838 using execution_space = typename memory_space::execution_space;
839
842
846 VerletList() = default;
847
875 template <class PositionType,
876 template <class, std::size_t, class...> class ArrayType,
877 class... Args>
879 PositionType x, const std::size_t begin, const std::size_t end,
880 const typename PositionType::value_type neighborhood_radius,
881 const typename PositionType::value_type cell_size_ratio,
882#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
883 const ArrayType<typename PositionType::value_type, num_space_dim,
884 Args...>
885 grid_min,
886 const ArrayType<typename PositionType::value_type, num_space_dim,
887 Args...>
888 grid_max,
889#else
890 const ArrayType<typename PositionType::value_type, num_space_dim>
891 grid_min,
892 const ArrayType<typename PositionType::value_type, num_space_dim>
893 grid_max,
894#endif
895 const std::size_t max_neigh = 0,
896 typename std::enable_if<( is_slice<PositionType>::value ||
897 Kokkos::is_view<PositionType>::value ),
898 int>::type* = 0 )
899 {
900 build( x, begin, end, neighborhood_radius, cell_size_ratio, grid_min,
901 grid_max, max_neigh );
902 }
903
931 template <class PositionType,
932 template <class, std::size_t, class...> class ArrayType,
933 class... Args>
934 void
935 build( PositionType x, const std::size_t begin, const std::size_t end,
936 const typename PositionType::value_type neighborhood_radius,
937 const typename PositionType::value_type cell_size_ratio,
938#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
939 const ArrayType<typename PositionType::value_type, num_space_dim,
940 Args...>
941 grid_min,
942 const ArrayType<typename PositionType::value_type, num_space_dim,
943 Args...>
944 grid_max,
945#else
946 const ArrayType<typename PositionType::value_type, num_space_dim>
947 grid_min,
948 const ArrayType<typename PositionType::value_type, num_space_dim>
949 grid_max,
950#endif
951 const std::size_t max_neigh = 0,
952 typename std::enable_if<( is_slice<PositionType>::value ||
953 Kokkos::is_view<PositionType>::value ),
954 int>::type* = 0 )
955 {
956 // Use the default execution space.
957 build( execution_space{}, x, begin, end, neighborhood_radius,
958 cell_size_ratio, grid_min, grid_max, max_neigh );
959 }
960
989 template <class PositionType, class RadiusType,
990 template <class, std::size_t, class...> class ArrayType,
991 class... Args>
993 PositionType x, const std::size_t begin, const std::size_t end,
994 const typename PositionType::value_type background_radius,
995 RadiusType neighborhood_radius,
996 const typename PositionType::value_type cell_size_ratio,
997#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
998 const ArrayType<typename PositionType::value_type, num_space_dim,
999 Args...>
1000 grid_min,
1001 const ArrayType<typename PositionType::value_type, num_space_dim,
1002 Args...>
1003 grid_max,
1004#else
1005 const ArrayType<typename PositionType::value_type, num_space_dim>
1006 grid_min,
1007 const ArrayType<typename PositionType::value_type, num_space_dim>
1008 grid_max,
1009#endif
1010 const std::size_t max_neigh = 0,
1011 typename std::enable_if<( is_slice<PositionType>::value ||
1012 Kokkos::is_view<PositionType>::value ),
1013 int>::type* = 0 )
1014 {
1015 build( x, begin, end, background_radius, neighborhood_radius,
1016 cell_size_ratio, grid_min, grid_max, max_neigh );
1017 }
1018
1039 template <class PositionType,
1040 template <class, std::size_t, class...> class ArrayType,
1041 class... Args>
1043 PositionType x,
1044 const typename PositionType::value_type neighborhood_radius,
1045 const typename PositionType::value_type cell_size_ratio,
1046#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
1047 const ArrayType<typename PositionType::value_type, num_space_dim,
1048 Args...>
1049 grid_min,
1050 const ArrayType<typename PositionType::value_type, num_space_dim,
1051 Args...>
1052 grid_max,
1053#else
1054 const ArrayType<typename PositionType::value_type, num_space_dim>
1055 grid_min,
1056 const ArrayType<typename PositionType::value_type, num_space_dim>
1057 grid_max,
1058#endif
1059 const std::size_t max_neigh = 0,
1060 typename std::enable_if<( is_slice<PositionType>::value ||
1061 Kokkos::is_view<PositionType>::value ),
1062 int>::type* = 0 )
1063 {
1064 build( x, neighborhood_radius, cell_size_ratio, grid_min, grid_max,
1065 max_neigh );
1066 }
1067
1072 template <class PositionType>
1074 PositionType x, const std::size_t begin, const std::size_t end,
1075 const typename PositionType::value_type neighborhood_radius,
1076 const typename PositionType::value_type cell_size_ratio,
1077 const typename PositionType::value_type grid_min[num_space_dim],
1078 const typename PositionType::value_type grid_max[num_space_dim],
1079 const std::size_t max_neigh = 0,
1080 typename std::enable_if<( is_slice<PositionType>::value ||
1081 Kokkos::is_view<PositionType>::value ),
1082 int>::type* = 0 )
1083 {
1084 build( x, begin, end, neighborhood_radius, cell_size_ratio, grid_min,
1085 grid_max, max_neigh );
1086 }
1087
1092 template <class PositionType>
1094 PositionType x,
1095 const typename PositionType::value_type neighborhood_radius,
1096 const typename PositionType::value_type cell_size_ratio,
1097 const typename PositionType::value_type grid_min[num_space_dim],
1098 const typename PositionType::value_type grid_max[num_space_dim],
1099 const std::size_t max_neigh = 0,
1100 typename std::enable_if<( is_slice<PositionType>::value ||
1101 Kokkos::is_view<PositionType>::value ),
1102 int>::type* = 0 )
1103 {
1104 build( x, neighborhood_radius, cell_size_ratio, grid_min, grid_max,
1105 max_neigh );
1106 }
1107
1112 template <class PositionType, class RadiusType>
1114 PositionType x, const std::size_t begin, const std::size_t end,
1115 const typename PositionType::value_type background_radius,
1116 RadiusType neighborhood_radius,
1117 const typename PositionType::value_type cell_size_ratio,
1118 const typename PositionType::value_type grid_min[num_space_dim],
1119 const typename PositionType::value_type grid_max[num_space_dim],
1120 const std::size_t max_neigh = 0,
1121 typename std::enable_if<( is_slice<PositionType>::value ||
1122 Kokkos::is_view<PositionType>::value ),
1123 int>::type* = 0 )
1124 {
1125 build( x, begin, end, background_radius, neighborhood_radius,
1126 cell_size_ratio, grid_min, grid_max, max_neigh );
1127 }
1128
1157 template <class PositionType, class RadiusType,
1158 template <class, std::size_t, class...> class ArrayType,
1159 class... Args>
1160 void build( PositionType x, const std::size_t begin, const std::size_t end,
1161 const typename PositionType::value_type background_radius,
1162 RadiusType neighborhood_radius,
1163 const typename PositionType::value_type cell_size_ratio,
1164#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
1165 const ArrayType<typename PositionType::value_type,
1166 num_space_dim, Args...>
1167 grid_min,
1168 const ArrayType<typename PositionType::value_type,
1169 num_space_dim, Args...>
1170 grid_max,
1171#else
1172 const ArrayType<typename PositionType::value_type,
1174 grid_min,
1175 const ArrayType<typename PositionType::value_type,
1177 grid_max,
1178#endif
1179 const std::size_t max_neigh = 0 )
1180 {
1181 build( execution_space{}, x, begin, end, background_radius,
1182 neighborhood_radius, cell_size_ratio, grid_min, grid_max,
1183 max_neigh );
1184 }
1185
1206 template <class PositionType,
1207 template <class, std::size_t, class...> class ArrayType,
1208 class... Args>
1209 void
1210 build( PositionType x,
1211 const typename PositionType::value_type neighborhood_radius,
1212 const typename PositionType::value_type cell_size_ratio,
1213#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
1214 const ArrayType<typename PositionType::value_type, num_space_dim,
1215 Args...>
1216 grid_min,
1217 const ArrayType<typename PositionType::value_type, num_space_dim,
1218 Args...>
1219 grid_max,
1220#else
1221 const ArrayType<typename PositionType::value_type, num_space_dim>
1222 grid_min,
1223 const ArrayType<typename PositionType::value_type, num_space_dim>
1224 grid_max,
1225#endif
1226 const std::size_t max_neigh = 0,
1227 typename std::enable_if<( is_slice<PositionType>::value ||
1228 Kokkos::is_view<PositionType>::value ),
1229 int>::type* = 0 )
1230 {
1231 build( x, 0, size( x ), neighborhood_radius, cell_size_ratio, grid_min,
1232 grid_max, max_neigh );
1233 }
1234
1239 template <class PositionType>
1240 void
1241 build( PositionType x, const std::size_t begin, const std::size_t end,
1242 const typename PositionType::value_type neighborhood_radius,
1243 const typename PositionType::value_type cell_size_ratio,
1244 const typename PositionType::value_type grid_min[num_space_dim],
1245 const typename PositionType::value_type grid_max[num_space_dim],
1246 const std::size_t max_neigh = 0,
1247 typename std::enable_if<( is_slice<PositionType>::value ||
1248 Kokkos::is_view<PositionType>::value ),
1249 int>::type* = 0 )
1250 {
1251 // Use the default execution space.
1252 build( execution_space{}, x, begin, end, neighborhood_radius,
1253 cell_size_ratio, grid_min, grid_max, max_neigh );
1254 }
1255
1260 template <class PositionType, class ExecutionSpace>
1261 void
1262 build( ExecutionSpace exec_space, PositionType x, const std::size_t begin,
1263 const std::size_t end,
1264 const typename PositionType::value_type neighborhood_radius,
1265 const typename PositionType::value_type cell_size_ratio,
1266 const typename PositionType::value_type grid_min[num_space_dim],
1267 const typename PositionType::value_type grid_max[num_space_dim],
1268 const std::size_t max_neigh = 0,
1269 typename std::enable_if<( is_slice<PositionType>::value ||
1270 Kokkos::is_view<PositionType>::value ),
1271 int>::type* = 0 )
1272 {
1273 auto kokkos_min =
1275 grid_min );
1276 auto kokkos_max =
1278 grid_max );
1279 build( exec_space, x, begin, end, neighborhood_radius, cell_size_ratio,
1280 kokkos_min, kokkos_max, max_neigh );
1281 }
1282
1287 template <class PositionType, class RadiusType>
1288 void build( PositionType x, const std::size_t begin, const std::size_t end,
1289 const typename PositionType::value_type background_radius,
1290 RadiusType neighborhood_radius,
1291 const typename PositionType::value_type cell_size_ratio,
1292 const typename PositionType::value_type grid_min[num_space_dim],
1293 const typename PositionType::value_type grid_max[num_space_dim],
1294 const std::size_t max_neigh = 0 )
1295 {
1296 // Use the default execution space.
1297 build( execution_space{}, x, begin, end, background_radius,
1298 neighborhood_radius, cell_size_ratio, grid_min, grid_max,
1299 max_neigh );
1300 }
1301
1306 template <class PositionType>
1307 void
1308 build( PositionType x,
1309 const typename PositionType::value_type neighborhood_radius,
1310 const typename PositionType::value_type cell_size_ratio,
1311 const typename PositionType::value_type grid_min[num_space_dim],
1312 const typename PositionType::value_type grid_max[num_space_dim],
1313 const std::size_t max_neigh = 0,
1314 typename std::enable_if<( is_slice<PositionType>::value ||
1315 Kokkos::is_view<PositionType>::value ),
1316 int>::type* = 0 )
1317 {
1318 build( x, 0, size( x ), neighborhood_radius, cell_size_ratio, grid_min,
1319 grid_max, max_neigh );
1320 }
1321
1326 template <class PositionType, class RadiusType, class ExecutionSpace>
1327 void build( ExecutionSpace exec_space, PositionType x,
1328 const std::size_t begin, const std::size_t end,
1329 const typename PositionType::value_type background_radius,
1330 RadiusType neighborhood_radius,
1331 const typename PositionType::value_type cell_size_ratio,
1332 const typename PositionType::value_type grid_min[num_space_dim],
1333 const typename PositionType::value_type grid_max[num_space_dim],
1334 const std::size_t max_neigh = 0 )
1335 {
1336 auto kokkos_min =
1338 grid_min );
1339 auto kokkos_max =
1341 grid_max );
1342 build( exec_space, x, begin, end, background_radius,
1343 neighborhood_radius, cell_size_ratio, kokkos_min, kokkos_max,
1344 max_neigh );
1345 }
1346
1351 template <class PositionType, class ExecutionSpace,
1352 template <class, std::size_t, class...> class ArrayType,
1353 class... Args>
1354 void
1355 build( ExecutionSpace, PositionType x, const std::size_t begin,
1356 const std::size_t end,
1357 const typename PositionType::value_type neighborhood_radius,
1358 const typename PositionType::value_type cell_size_ratio,
1359#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
1360 const ArrayType<typename PositionType::value_type, num_space_dim,
1361 Args...>
1362 grid_min,
1363 const ArrayType<typename PositionType::value_type, num_space_dim,
1364 Args...>
1365 grid_max,
1366#else
1367 const ArrayType<typename PositionType::value_type, num_space_dim>
1368 grid_min,
1369 const ArrayType<typename PositionType::value_type, num_space_dim>
1370 grid_max,
1371#endif
1372 const std::size_t max_neigh = 0,
1373 typename std::enable_if<( is_slice<PositionType>::value ||
1374 Kokkos::is_view<PositionType>::value ),
1375 int>::type* = 0 )
1376 {
1377 Kokkos::Profiling::ScopedRegion region( "Cabana::VerletList::build" );
1378
1380
1381 assert( end >= begin );
1382 assert( end <= size( x ) );
1383
1384 using device_type = Kokkos::Device<ExecutionSpace, memory_space>;
1385 // Create a builder functor.
1386 auto builder =
1387 Impl::createVerletListBuilder<num_space_dim, device_type,
1388 AlgorithmTag, LayoutTag, BuildTag>(
1389 x, begin, end, neighborhood_radius, cell_size_ratio, grid_min,
1390 grid_max, max_neigh );
1391 buildImpl( builder );
1392 }
1393
1398 template <class PositionType, class RadiusType, class ExecutionSpace,
1399 template <class, std::size_t, class...> class ArrayType,
1400 class... Args>
1401 void build( ExecutionSpace, PositionType x, const std::size_t begin,
1402 const std::size_t end,
1403 const typename PositionType::value_type background_radius,
1404 RadiusType neighborhood_radius,
1405 const typename PositionType::value_type cell_size_ratio,
1406#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
1407 const ArrayType<typename PositionType::value_type,
1408 num_space_dim, Args...>
1409 grid_min,
1410 const ArrayType<typename PositionType::value_type,
1411 num_space_dim, Args...>
1412 grid_max,
1413#else
1414 const ArrayType<typename PositionType::value_type,
1416 grid_min,
1417 const ArrayType<typename PositionType::value_type,
1419 grid_max,
1420#endif
1421 const std::size_t max_neigh = 0 )
1422 {
1423 Kokkos::Profiling::ScopedRegion region( "Cabana::VerletList::build" );
1424
1426
1427 assert( end >= begin );
1428 assert( end <= size( x ) );
1429
1430 // Create a builder functor.
1431 using device_type = Kokkos::Device<ExecutionSpace, memory_space>;
1432 auto builder =
1433 Impl::createVerletListBuilder<num_space_dim, device_type,
1434 AlgorithmTag, LayoutTag, BuildTag>(
1435 x, begin, end, background_radius, neighborhood_radius,
1436 cell_size_ratio, grid_min, grid_max, max_neigh );
1437 buildImpl( builder );
1438 }
1439
1441 template <class BuilderType>
1442 void buildImpl( BuilderType builder )
1443 {
1444 // For each particle in the range check each neighboring bin for
1445 // neighbor particles. Bins are at least the size of the
1446 // neighborhood radius so the bin in which the particle resides and
1447 // any surrounding bins are guaranteed to contain the neighboring
1448 // particles. For CSR lists, we count, then fill neighbors. For 2D
1449 // lists, we count and fill at the same time, unless the array size
1450 // is exceeded, at which point only counting is continued to
1451 // reallocate and refill.
1452 typename BuilderType::FillNeighborsPolicy fill_policy(
1453 builder.bin_data_1d.numBin(), Kokkos::AUTO, 4 );
1454 if ( builder.count )
1455 {
1456 typename BuilderType::CountNeighborsPolicy count_policy(
1457 builder.bin_data_1d.numBin(), Kokkos::AUTO, 4 );
1458 Kokkos::parallel_for( "Cabana::VerletList::count_neighbors",
1459 count_policy, builder );
1460 }
1461 else
1462 {
1463 builder.processCounts( LayoutTag() );
1464 Kokkos::parallel_for( "Cabana::VerletList::fill_neighbors",
1465 fill_policy, builder );
1466 }
1467 Kokkos::fence();
1468
1469 // Process the counts by computing offsets and allocating the neighbor
1470 // list, if needed.
1471 builder.processCounts( LayoutTag() );
1472
1473 // For each particle in the range fill (or refill) its part of the
1474 // neighbor list.
1475 if ( builder.count or builder.refill )
1476 {
1477 Kokkos::parallel_for( "Cabana::VerletList::fill_neighbors",
1478 fill_policy, builder );
1479 Kokkos::fence();
1480 }
1481
1482 // Get the data from the builder.
1483 _data = builder._data;
1484 }
1486
1488 KOKKOS_INLINE_FUNCTION
1489 void setNeighbor( const std::size_t particle_index,
1490 const std::size_t neighbor_index,
1491 const int new_index ) const
1492 {
1493 _data.setNeighbor( particle_index, neighbor_index, new_index );
1494 }
1495};
1496
1497//---------------------------------------------------------------------------//
1498// VerletList creation functions.
1499//---------------------------------------------------------------------------//
1500
1528template <class AlgorithmTag, class LayoutTag, class BuildTag,
1529 class PositionType,
1530 template <class, std::size_t, class...> class ArrayType,
1531 std::size_t NumSpaceDim, class... Args>
1533 PositionType positions, const std::size_t begin, const std::size_t end,
1534 const typename PositionType::value_type radius,
1535 const typename PositionType::value_type cell_size_ratio,
1536#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
1537 const ArrayType<typename PositionType::value_type, NumSpaceDim, Args...>
1538 grid_min,
1539 const ArrayType<typename PositionType::value_type, NumSpaceDim, Args...>
1540 grid_max,
1541#else
1542 const ArrayType<typename PositionType::value_type, NumSpaceDim> grid_min,
1543 const ArrayType<typename PositionType::value_type, NumSpaceDim> grid_max,
1544#endif
1545 const std::size_t max_neigh = 0 )
1546{
1547 using memory_space = typename PositionType::memory_space;
1548 return Cabana::VerletList<memory_space, AlgorithmTag, LayoutTag, BuildTag,
1549 NumSpaceDim>( positions, begin, end, radius,
1550 cell_size_ratio, grid_min, grid_max,
1551 max_neigh );
1552}
1553
1574template <class AlgorithmTag, class LayoutTag, class BuildTag,
1575 class PositionType,
1576 template <class, std::size_t, class...> class ArrayType,
1577 std::size_t NumSpaceDim, class... Args>
1579 const PositionType& positions,
1580 const typename PositionType::value_type radius,
1581 const typename PositionType::value_type cell_size_ratio,
1582#ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
1583 const ArrayType<typename PositionType::value_type, NumSpaceDim, Args...>
1584 grid_min,
1585 const ArrayType<typename PositionType::value_type, NumSpaceDim, Args...>
1586 grid_max,
1587#else
1588 const ArrayType<typename PositionType::value_type, NumSpaceDim> grid_min,
1589 const ArrayType<typename PositionType::value_type, NumSpaceDim> grid_max,
1590#endif
1591 const std::size_t max_neigh = 0 )
1592{
1593 using memory_space = typename PositionType::memory_space;
1594 return Cabana::VerletList<memory_space, AlgorithmTag, LayoutTag, BuildTag,
1595 NumSpaceDim>( positions, radius, cell_size_ratio,
1596 grid_min, grid_max, max_neigh );
1597}
1598
1599//---------------------------------------------------------------------------//
1600// Neighbor list interface implementation.
1601//---------------------------------------------------------------------------//
1603template <class MemorySpace, class AlgorithmTag, class BuildTag,
1604 std::size_t Dim>
1606 VerletList<MemorySpace, AlgorithmTag, VerletLayoutCSR, BuildTag, Dim>>
1607{
1608 public:
1610 using memory_space = MemorySpace;
1614
1616 KOKKOS_INLINE_FUNCTION
1617 static std::size_t totalNeighbor( const list_type& list )
1618 {
1619 // Size of the allocated memory gives total neighbors.
1620 return list._data.neighbors.extent( 0 );
1621 }
1622
1624 KOKKOS_INLINE_FUNCTION
1625 static std::size_t maxNeighbor( const list_type& list )
1626 {
1627 std::size_t num_p = list._data.counts.size();
1628 return Impl::maxNeighbor( list, num_p );
1629 }
1630
1632 KOKKOS_INLINE_FUNCTION
1633 static std::size_t numNeighbor( const list_type& list,
1634 const std::size_t particle_index )
1635 {
1636 return list._data.counts( particle_index );
1637 }
1638
1641 KOKKOS_INLINE_FUNCTION
1642 static std::size_t getNeighbor( const list_type& list,
1643 const std::size_t particle_index,
1644 const std::size_t neighbor_index )
1645 {
1646 return list._data.neighbors( list._data.offsets( particle_index ) +
1647 neighbor_index );
1648 }
1649};
1650
1651//---------------------------------------------------------------------------//
1653template <class MemorySpace, class AlgorithmTag, class BuildTag,
1654 std::size_t Dim>
1656 VerletList<MemorySpace, AlgorithmTag, VerletLayout2D, BuildTag, Dim>>
1657{
1658 public:
1660 using memory_space = MemorySpace;
1664
1666 KOKKOS_INLINE_FUNCTION
1667 static std::size_t totalNeighbor( const list_type& list )
1668 {
1669 std::size_t num_p = list._data.counts.size();
1670 return Impl::totalNeighbor( list, num_p );
1671 }
1672
1674 KOKKOS_INLINE_FUNCTION
1675 static std::size_t maxNeighbor( const list_type& list )
1676 {
1677 // Stored during neighbor search.
1678 return list._data.max_n;
1679 }
1680
1682 KOKKOS_INLINE_FUNCTION
1683 static std::size_t numNeighbor( const list_type& list,
1684 const std::size_t particle_index )
1685 {
1686 return list._data.counts( particle_index );
1687 }
1688
1691 KOKKOS_INLINE_FUNCTION
1692 static std::size_t getNeighbor( const list_type& list,
1693 const std::size_t particle_index,
1694 const std::size_t neighbor_index )
1695 {
1696 return list._data.neighbors( particle_index, neighbor_index );
1697 }
1698};
1699
1700//---------------------------------------------------------------------------//
1701
1702} // end namespace Cabana
1703
1704#endif // end CABANA_VERLETLIST_HPP
std::enable_if_t< 3==Array_t::num_space_dim, void > update(Array_t &a, const typename Array_t::value_type alpha, const Array_t &b, const typename Array_t::value_type beta, DecompositionTag tag)
Update two vectors such that a = alpha * a + beta * b. 3D specialization.
Definition Cabana_Grid_Array.hpp:617
KOKKOS_INLINE_FUNCTION std::enable_if_t< 3==SplineDataType::num_space_dim, void > value(const ViewType &view, const SplineDataType &sd, PointDataType &result, typename std::enable_if<(std::rank< PointDataType >::value==0), void * >::type=0)
Interpolate a scalar value to a point. 3D specialization.
Definition Cabana_Grid_Interpolation.hpp:56
Linked cell list binning (spatial sorting) and neighbor iteration.
Neighbor list interface.
KOKKOS_INLINE_FUNCTION std::size_t maxNeighbor(const ListType &list, const std::size_t num_particles)
Iterate to find the maximum number of neighbors.
Definition Cabana_NeighborList.hpp:273
KOKKOS_INLINE_FUNCTION std::size_t totalNeighbor(const ListType &list, const std::size_t num_particles)
Iterate to get the total number of neighbors.
Definition Cabana_NeighborList.hpp:261
SIMD and neighbor extension of Kokkos parallel iteration.
Neighborhood discriminator.
Definition Cabana_NeighborList.hpp:63
static KOKKOS_INLINE_FUNCTION std::size_t numNeighbor(const list_type &list, const std::size_t particle_index)
Get the number of neighbors for a given particle index.
Definition Cabana_VerletList.hpp:1683
static KOKKOS_INLINE_FUNCTION std::size_t maxNeighbor(const list_type &list)
Get the maximum number of neighbors per particle.
Definition Cabana_VerletList.hpp:1675
static KOKKOS_INLINE_FUNCTION std::size_t getNeighbor(const list_type &list, const std::size_t particle_index, const std::size_t neighbor_index)
Definition Cabana_VerletList.hpp:1692
static KOKKOS_INLINE_FUNCTION std::size_t totalNeighbor(const list_type &list)
Get the total number of neighbors across all particles.
Definition Cabana_VerletList.hpp:1667
VerletList< MemorySpace, AlgorithmTag, VerletLayout2D, BuildTag, Dim > list_type
Neighbor list type.
Definition Cabana_VerletList.hpp:1662
MemorySpace memory_space
Kokkos memory space.
Definition Cabana_VerletList.hpp:1660
static KOKKOS_INLINE_FUNCTION std::size_t totalNeighbor(const list_type &list)
Get the total number of neighbors across all particles.
Definition Cabana_VerletList.hpp:1617
MemorySpace memory_space
Kokkos memory space.
Definition Cabana_VerletList.hpp:1610
static KOKKOS_INLINE_FUNCTION std::size_t numNeighbor(const list_type &list, const std::size_t particle_index)
Get the number of neighbors for a given particle index.
Definition Cabana_VerletList.hpp:1633
VerletList< MemorySpace, AlgorithmTag, VerletLayoutCSR, BuildTag, Dim > list_type
Neighbor list type.
Definition Cabana_VerletList.hpp:1612
static KOKKOS_INLINE_FUNCTION std::size_t maxNeighbor(const list_type &list)
Get the maximum number of neighbors across all particles.
Definition Cabana_VerletList.hpp:1625
static KOKKOS_INLINE_FUNCTION std::size_t getNeighbor(const list_type &list, const std::size_t particle_index, const std::size_t neighbor_index)
Definition Cabana_VerletList.hpp:1642
Neighbor list interface. Provides an interface callable at the functor level that gives access to nei...
Definition Cabana_NeighborList.hpp:223
Neighbor operations are executed with team parallelism.
Definition Cabana_Parallel.hpp:206
Neighbor operations are executed with team vector parallelism.
Definition Cabana_Parallel.hpp:211
Neighbor list implementation based on binning particles on a Cartesian grid with cells of the same si...
Definition Cabana_VerletList.hpp:827
void build(ExecutionSpace exec_space, PositionType x, const std::size_t begin, const std::size_t end, const typename PositionType::value_type neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const typename PositionType::value_type grid_min[num_space_dim], const typename PositionType::value_type grid_max[num_space_dim], const std::size_t max_neigh=0, typename std::enable_if<(is_slice< PositionType >::value||Kokkos::is_view< PositionType >::value), int >::type *=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:1262
typename memory_space::execution_space execution_space
Kokkos default execution space for this memory space.
Definition Cabana_VerletList.hpp:838
VerletList(PositionType x, const std::size_t begin, const std::size_t end, const typename PositionType::value_type neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const ArrayType< typename PositionType::value_type, num_space_dim > grid_min, const ArrayType< typename PositionType::value_type, num_space_dim > grid_max, const std::size_t max_neigh=0, typename std::enable_if<(is_slice< PositionType >::value||Kokkos::is_view< PositionType >::value), int >::type *=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:878
VerletList(PositionType x, const std::size_t begin, const std::size_t end, const typename PositionType::value_type background_radius, RadiusType neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const ArrayType< typename PositionType::value_type, num_space_dim > grid_min, const ArrayType< typename PositionType::value_type, num_space_dim > grid_max, const std::size_t max_neigh=0, typename std::enable_if<(is_slice< PositionType >::value||Kokkos::is_view< PositionType >::value), int >::type *=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:992
VerletList(PositionType x, const typename PositionType::value_type neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const ArrayType< typename PositionType::value_type, num_space_dim > grid_min, const ArrayType< typename PositionType::value_type, num_space_dim > grid_max, const std::size_t max_neigh=0, typename std::enable_if<(is_slice< PositionType >::value||Kokkos::is_view< PositionType >::value), int >::type *=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:1042
VerletList(PositionType x, const std::size_t begin, const std::size_t end, const typename PositionType::value_type background_radius, RadiusType neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const typename PositionType::value_type grid_min[num_space_dim], const typename PositionType::value_type grid_max[num_space_dim], const std::size_t max_neigh=0, typename std::enable_if<(is_slice< PositionType >::value||Kokkos::is_view< PositionType >::value), int >::type *=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:1113
void build(ExecutionSpace, PositionType x, const std::size_t begin, const std::size_t end, const typename PositionType::value_type background_radius, RadiusType neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const ArrayType< typename PositionType::value_type, num_space_dim > grid_min, const ArrayType< typename PositionType::value_type, num_space_dim > grid_max, const std::size_t max_neigh=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:1401
void build(ExecutionSpace exec_space, PositionType x, const std::size_t begin, const std::size_t end, const typename PositionType::value_type background_radius, RadiusType neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const typename PositionType::value_type grid_min[num_space_dim], const typename PositionType::value_type grid_max[num_space_dim], const std::size_t max_neigh=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:1327
void build(PositionType x, const typename PositionType::value_type neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const typename PositionType::value_type grid_min[num_space_dim], const typename PositionType::value_type grid_max[num_space_dim], const std::size_t max_neigh=0, typename std::enable_if<(is_slice< PositionType >::value||Kokkos::is_view< PositionType >::value), int >::type *=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:1308
VerletList()=default
Default constructor.
KOKKOS_INLINE_FUNCTION void setNeighbor(const std::size_t particle_index, const std::size_t neighbor_index, const int new_index) const
Modify a neighbor in the list; for example, mark it as a broken bond.
Definition Cabana_VerletList.hpp:1489
VerletListData< memory_space, VerletLayoutCSR > _data
Definition Cabana_VerletList.hpp:841
void build(PositionType x, const std::size_t begin, const std::size_t end, const typename PositionType::value_type neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const typename PositionType::value_type grid_min[num_space_dim], const typename PositionType::value_type grid_max[num_space_dim], const std::size_t max_neigh=0, typename std::enable_if<(is_slice< PositionType >::value||Kokkos::is_view< PositionType >::value), int >::type *=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:1241
void build(PositionType x, const std::size_t begin, const std::size_t end, const typename PositionType::value_type background_radius, RadiusType neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const ArrayType< typename PositionType::value_type, num_space_dim > grid_min, const ArrayType< typename PositionType::value_type, num_space_dim > grid_max, const std::size_t max_neigh=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:1160
void build(PositionType x, const typename PositionType::value_type neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const ArrayType< typename PositionType::value_type, num_space_dim > grid_min, const ArrayType< typename PositionType::value_type, num_space_dim > grid_max, const std::size_t max_neigh=0, typename std::enable_if<(is_slice< PositionType >::value||Kokkos::is_view< PositionType >::value), int >::type *=0)
VerletList constructor. Given a list of particle positions and a neighborhood radius calculate the ne...
Definition Cabana_VerletList.hpp:1210
void build(PositionType x, const std::size_t begin, const std::size_t end, const typename PositionType::value_type background_radius, RadiusType neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const typename PositionType::value_type grid_min[num_space_dim], const typename PositionType::value_type grid_max[num_space_dim], const std::size_t max_neigh=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:1288
VerletList(PositionType x, const std::size_t begin, const std::size_t end, const typename PositionType::value_type neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const typename PositionType::value_type grid_min[num_space_dim], const typename PositionType::value_type grid_max[num_space_dim], const std::size_t max_neigh=0, typename std::enable_if<(is_slice< PositionType >::value||Kokkos::is_view< PositionType >::value), int >::type *=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:1073
MemorySpace memory_space
Kokkos memory space in which the neighbor list data resides.
Definition Cabana_VerletList.hpp:835
void build(PositionType x, const std::size_t begin, const std::size_t end, const typename PositionType::value_type neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const ArrayType< typename PositionType::value_type, num_space_dim > grid_min, const ArrayType< typename PositionType::value_type, num_space_dim > grid_max, const std::size_t max_neigh=0, typename std::enable_if<(is_slice< PositionType >::value||Kokkos::is_view< PositionType >::value), int >::type *=0)
Definition Cabana_VerletList.hpp:935
static constexpr std::size_t num_space_dim
Definition Cabana_VerletList.hpp:832
VerletList(PositionType x, const typename PositionType::value_type neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const typename PositionType::value_type grid_min[num_space_dim], const typename PositionType::value_type grid_max[num_space_dim], const std::size_t max_neigh=0, typename std::enable_if<(is_slice< PositionType >::value||Kokkos::is_view< PositionType >::value), int >::type *=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list....
Definition Cabana_VerletList.hpp:1093
void build(ExecutionSpace, PositionType x, const std::size_t begin, const std::size_t end, const typename PositionType::value_type neighborhood_radius, const typename PositionType::value_type cell_size_ratio, const ArrayType< typename PositionType::value_type, num_space_dim > grid_min, const ArrayType< typename PositionType::value_type, num_space_dim > grid_max, const std::size_t max_neigh=0, typename std::enable_if<(is_slice< PositionType >::value||Kokkos::is_view< PositionType >::value), int >::type *=0)
Given a list of particle positions and a neighborhood radius calculate the neighbor list.
Definition Cabana_VerletList.hpp:1355
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36
auto size(SliceType slice, typename std::enable_if< is_slice< SliceType >::value, int >::type *=0)
Check slice size (differs from Kokkos View).
Definition Cabana_Slice.hpp:1019
auto copyArray(const std::array< Scalar, Dim > input)
Copy std::array into Kokkos::Array for potential device use.
Definition Cabana_Utils.hpp:32
auto createLinkedCellList(PositionType positions, const ArrayType< Scalar, NumSpaceDim > grid_delta, const ArrayType< Scalar, NumSpaceDim > grid_min, const ArrayType< Scalar, NumSpaceDim > grid_max)
Creation function for linked cell list.
Definition Cabana_LinkedCellList.hpp:918
auto createVerletList(PositionType positions, const std::size_t begin, const std::size_t end, const typename PositionType::value_type radius, const typename PositionType::value_type cell_size_ratio, const ArrayType< typename PositionType::value_type, NumSpaceDim > grid_min, const ArrayType< typename PositionType::value_type, NumSpaceDim > grid_max, const std::size_t max_neigh=0)
VerletList constructor. Given a list of particle positions and a neighborhood radius calculate the ne...
Definition Cabana_VerletList.hpp:1532
2D array neighbor list layout.
Definition Cabana_VerletList.hpp:40
CSR (compressed sparse row) neighbor list layout.
Definition Cabana_VerletList.hpp:35
KOKKOS_INLINE_FUNCTION void addNeighbor(const int pid, const int nid) const
Add a neighbor to the list.
Definition Cabana_VerletList.hpp:100
MemorySpace memory_space
Kokkos memory space.
Definition Cabana_VerletList.hpp:86
Kokkos::View< int *, memory_space > counts
Number of neighbors per particle.
Definition Cabana_VerletList.hpp:89
Kokkos::View< int **, memory_space > neighbors
Neighbor list.
Definition Cabana_VerletList.hpp:92
KOKKOS_INLINE_FUNCTION void setNeighbor(const int pid, const int nid, const int new_id) const
Modify a neighbor in the list.
Definition Cabana_VerletList.hpp:109
std::size_t max_n
Definition Cabana_VerletList.hpp:96
KOKKOS_INLINE_FUNCTION void setNeighbor(const int pid, const int nid, const int new_id) const
Modify a neighbor in the list.
Definition Cabana_VerletList.hpp:75
Kokkos::View< int *, memory_space > offsets
Offsets into the neighbor list.
Definition Cabana_VerletList.hpp:60
MemorySpace memory_space
Kokkos memory space.
Definition Cabana_VerletList.hpp:54
Kokkos::View< int *, memory_space > counts
Number of neighbors per particle.
Definition Cabana_VerletList.hpp:57
KOKKOS_INLINE_FUNCTION void addNeighbor(const int pid, const int nid) const
Add a neighbor to the list.
Definition Cabana_VerletList.hpp:67
Kokkos::View< int *, memory_space > neighbors
Neighbor list.
Definition Cabana_VerletList.hpp:63
Definition Cabana_VerletList.hpp:47
Definition Cabana_Types.hpp:88
Slice static type checker.
Definition Cabana_Slice.hpp:868