@@ -235,16 +235,69 @@ struct VerletListBuilder
235235 rsqr = neighborhood_radius * neighborhood_radius;
236236 }
237237
238- KOKKOS_INLINE_FUNCTION auto cutoff ( [[maybe_unused]] const int p ) const
238+ // Check if particle pair i-j is within cutoff, potentially with variable
239+ // radii.
240+ KOKKOS_INLINE_FUNCTION auto withinCutoff ( [[maybe_unused]] const int i,
241+ const double dist_sqr ) const
239242 {
240243 // Square the radius on the fly if using a per-particle field to avoid a
241244 // deep copy.
242245 if constexpr ( is_slice<RadiusType>::value ||
243246 Kokkos::is_view<RadiusType>::value )
244- return radius ( p ) * radius ( p );
247+ return dist_sqr <= radius ( i ) * radius ( i );
245248 // This value is already squared.
246249 else
247- return rsqr;
250+ return dist_sqr <= rsqr;
251+ }
252+
253+ // Check if potential neighbor j is NOT within cutoff, meaning particle i
254+ // should add instead for symmetry.
255+ KOKKOS_INLINE_FUNCTION auto
256+ neighborNotWithinCutoff ( [[maybe_unused]] const int j,
257+ [[maybe_unused]] const double dist_sqr ) const
258+ {
259+ // This neighbor needs to be added if they will not find this particle.
260+ if constexpr ( is_slice<RadiusType>::value ||
261+ Kokkos::is_view<RadiusType>::value )
262+ {
263+ return dist_sqr >= radius ( j ) * radius ( j );
264+ }
265+ else
266+ {
267+ // For a fixed radius, this will never occur.
268+ return false ;
269+ }
270+ }
271+
272+ // Count neighbors, with consideration for self particle i and neighbor j.
273+ KOKKOS_INLINE_FUNCTION auto countNeighbor ( const int i, const int j,
274+ const double dist_sqr ) const
275+ {
276+ int c = 0 ;
277+ // Always add self if within cutoff.
278+ if ( withinCutoff ( i, dist_sqr ) )
279+ {
280+ c++;
281+ // Add neighbor if they will not find this particle.
282+ if ( neighborNotWithinCutoff ( j, dist_sqr ) )
283+ c++;
284+ }
285+ return c;
286+ }
287+
288+ // Add neighbors, with consideration for self particle i and neighbor j.
289+ KOKKOS_INLINE_FUNCTION void addNeighbor ( const int i, const int j,
290+ const double dist_sqr ) const
291+ {
292+ // Always add self if within cutoff.
293+ if ( withinCutoff ( i, dist_sqr ) )
294+ {
295+ _data.addNeighbor ( i, j );
296+
297+ // Add neighbor if they will not find this particle.
298+ if ( neighborNotWithinCutoff ( j, dist_sqr ) )
299+ _data.addNeighbor ( j, i );
300+ }
248301 }
249302
250303 // Neighbor count team operator (only used for CSR lists).
@@ -295,9 +348,11 @@ struct VerletListBuilder
295348 {
296349 // See if we should actually check this box for
297350 // neighbors.
298- if ( linked_cell_list.cellStencil ()
299- .grid .minDistanceToPoint (
300- x_p, y_p, z_p, i, j, k ) <= rsqr )
351+ if ( withinCutoff (
352+ pid,
353+ linked_cell_list.cellStencil ()
354+ .grid .minDistanceToPoint (
355+ x_p, y_p, z_p, i, j, k ) ) )
301356 {
302357 std::size_t n_offset =
303358 linked_cell_list.binOffset ( i, j, k );
@@ -373,8 +428,7 @@ struct VerletListBuilder
373428 PositionValueType dist_sqr = dx * dx + dy * dy + dz * dz;
374429
375430 // If within the cutoff add to the count.
376- if ( dist_sqr <= cutoff ( pid ) )
377- local_count += 1 ;
431+ local_count += countNeighbor ( pid, nid, dist_sqr );
378432 }
379433 }
380434
@@ -512,9 +566,11 @@ struct VerletListBuilder
512566 {
513567 // See if we should actually check this box for
514568 // neighbors.
515- if ( linked_cell_list.cellStencil ()
516- .grid .minDistanceToPoint (
517- x_p, y_p, z_p, i, j, k ) <= rsqr )
569+ if ( withinCutoff (
570+ pid,
571+ linked_cell_list.cellStencil ()
572+ .grid .minDistanceToPoint (
573+ x_p, y_p, z_p, i, j, k ) ) )
518574 {
519575 // Check the particles in this bin to see if
520576 // they are neighbors.
@@ -583,10 +639,7 @@ struct VerletListBuilder
583639
584640 // If within the cutoff increment the neighbor count and add as a
585641 // neighbor at that index.
586- if ( dist_sqr <= cutoff ( pid ) )
587- {
588- _data.addNeighbor ( pid, nid );
589- }
642+ addNeighbor ( pid, nid, dist_sqr );
590643 }
591644 }
592645};
0 commit comments