|
| 1 | +struct NeighborListsNeighborhoodSearch{NDIMS, NHS, NL, PB} |
| 2 | + neighborhood_search :: NHS |
| 3 | + neighbor_lists :: NL |
| 4 | + periodic_box :: PB |
| 5 | + |
| 6 | + function NeighborListsNeighborhoodSearch{NDIMS}(search_radius, n_particles; |
| 7 | + periodic_box_min_corner = nothing, |
| 8 | + periodic_box_max_corner = nothing) where { |
| 9 | + NDIMS |
| 10 | + } |
| 11 | + backend = GridNeighborhoodSearch{NDIMS}(search_radius, n_particles, |
| 12 | + periodic_box_min_corner = periodic_box_min_corner, |
| 13 | + periodic_box_max_corner = periodic_box_max_corner) |
| 14 | + |
| 15 | + neighbor_lists = Vector{Vector{Int}}() |
| 16 | + |
| 17 | + new{NDIMS, typeof(backend), |
| 18 | + typeof(neighbor_lists), |
| 19 | + typeof(backend.periodic_box)}(backend, neighbor_lists, backend.periodic_box) |
| 20 | + end |
| 21 | +end |
| 22 | + |
| 23 | +@inline function Base.ndims(neighborhood_search::NeighborListsNeighborhoodSearch{NDIMS}) where { |
| 24 | + NDIMS |
| 25 | + } |
| 26 | + return NDIMS |
| 27 | +end |
| 28 | + |
| 29 | +function initialize!(search::NeighborListsNeighborhoodSearch, |
| 30 | + x::AbstractMatrix, y::AbstractMatrix) |
| 31 | + (; neighborhood_search, neighbor_lists) = search |
| 32 | + |
| 33 | + initialize!(neighborhood_search, x, y) |
| 34 | + |
| 35 | + initialize_neighbor_lists!(neighbor_lists, neighborhood_search, x, y) |
| 36 | +end |
| 37 | + |
| 38 | +function update!(search::NeighborListsNeighborhoodSearch, x::AbstractMatrix, |
| 39 | + y::AbstractMatrix; |
| 40 | + particles_moving = (true, true)) |
| 41 | + (; neighborhood_search, neighbor_lists) = search |
| 42 | + |
| 43 | + update!(neighborhood_search, x, y, particles_moving = particles_moving) |
| 44 | + |
| 45 | + initialize_neighbor_lists!(neighbor_lists, neighborhood_search, x, y) |
| 46 | +end |
| 47 | + |
| 48 | +function initialize_neighbor_lists!(neighbor_lists, neighborhood_search, x, y) |
| 49 | + # Initialize neighbor lists |
| 50 | + empty!(neighbor_lists) |
| 51 | + resize!(neighbor_lists, size(x, 2)) |
| 52 | + for i in eachindex(neighbor_lists) |
| 53 | + neighbor_lists[i] = Int[] |
| 54 | + end |
| 55 | + |
| 56 | + # Compute neighbor lists |
| 57 | + for_particle_neighbor(x, y, neighborhood_search) do particle, neighbor, _, _ |
| 58 | + push!(neighbor_lists[particle], neighbor) |
| 59 | + end |
| 60 | +end |
| 61 | + |
| 62 | +@inline function for_particle_neighbor_inner(f, system_coords, neighbor_system_coords, |
| 63 | + neighborhood_search::NeighborListsNeighborhoodSearch, |
| 64 | + particle) |
| 65 | + (; periodic_box, neighbor_lists) = neighborhood_search |
| 66 | + (; search_radius) = neighborhood_search.neighborhood_search |
| 67 | + |
| 68 | + particle_coords = extract_svector(system_coords, Val(ndims(neighborhood_search)), |
| 69 | + particle) |
| 70 | + for neighbor in neighbor_lists[particle] |
| 71 | + neighbor_coords = extract_svector(neighbor_system_coords, |
| 72 | + Val(ndims(neighborhood_search)), neighbor) |
| 73 | + |
| 74 | + pos_diff = particle_coords - neighbor_coords |
| 75 | + distance2 = dot(pos_diff, pos_diff) |
| 76 | + |
| 77 | + pos_diff, distance2 = compute_periodic_distance(pos_diff, distance2, search_radius, |
| 78 | + periodic_box) |
| 79 | + |
| 80 | + distance = sqrt(distance2) |
| 81 | + |
| 82 | + # Inline to avoid loss of performance |
| 83 | + # compared to not using `for_particle_neighbor`. |
| 84 | + @inline f(particle, neighbor, pos_diff, distance) |
| 85 | + end |
| 86 | +end |
0 commit comments