@@ -2,31 +2,60 @@ using StaticArrays
22
33abstract type NeighbourList end
44
5+ """ Build or update the neighbour list for `system` using its current neighbour list type.
6+
7+ This dispatches to the concrete `build_neighbour_list!` method for the active neighbour list implementation.
8+ """
59function build_neighbour_list! (system:: Particles )
610 return build_neighbour_list! (system, get_neighbour_list (system))
711end
812
13+ """ A no-op neighbour list implementation: always empty.
14+
15+ Useful for testing or systems where no neighbour list is desired.
16+ """
917struct EmptyList <: NeighbourList end
1018
19+ """ Construct an `EmptyList` (ignores box, rcut, N).
20+ """
1121function EmptyList (box, rcut, N)
1222 return EmptyList ()
1323end
1424
25+ """ No-op build for `EmptyList`.
26+ """
1527function build_neighbour_list! (:: Particles ,:: EmptyList )
1628 return nothing
1729end
1830
31+ """ No-op update for `EmptyList`.
32+ """
1933function update_neighbour_list! (i, c, c2, :: EmptyList )
2034 return nothing
2135end
2236
37+ """ Return placeholder old and new cell indices for `EmptyList`.
38+
39+ Always returns (1,1) as no cells are tracked.
40+ """
2341function old_new_cell (:: Particles , i, :: EmptyList )
2442 return 1 , 1
2543end
2644
45+ """ Return the scalar cell index of particle `i` stored in `neighbour_list`.
46+ """
2747function get_cell_index (i:: Int , neighbour_list:: NeighbourList )
2848 return neighbour_list. cs[i]
2949end
50+ """ Cell-list neighbour list implementation.
51+
52+ Fields:
53+ - `cs`: per-particle scalar cell index
54+ - `box`: cell dimensions
55+ - `ncells`: number of cells per dimension
56+ - `cells`: vectors of particle indices in each cell
57+ - `neighbour_cells`: precomputed neighbouring cell indices for each cell
58+ """
3059struct CellList{T<: AbstractFloat , d} <: NeighbourList
3160 cs:: Vector{Int}
3261 box:: SVector{d,T}
@@ -35,10 +64,16 @@ struct CellList{T<:AbstractFloat, d} <: NeighbourList
3564 neighbour_cells:: Vector{Vector{Int}} # List of neighbouring cells
3665end
3766
67+ """ Return the scalar cell index corresponding to `mc` using `neighbour_list` metadata.
68+ """
3869function cell_index (neighbour_list:: NeighbourList , mc:: NTuple{d,Int} ) where {d}
3970 return cell_index (neighbour_list. ncells, mc)
4071end
4172
73+ """ Compute a scalar cell index from the multi-dimensional cell coordinate `mc`.
74+
75+ Uses row-major ordering with periodic boundary treatment via `fold_back`.
76+ """
4277function cell_index (ncells:: NTuple{d, Int} , mc:: NTuple{d,Int} ) where {d}
4378 mc_fold = fold_back (mc, ncells)
4479 c = 1
@@ -50,6 +85,10 @@ function cell_index(ncells::NTuple{d, Int}, mc::NTuple{d,Int}) where {d}
5085 return c
5186end
5287
88+ """ Build for each scalar cell index the list of neighbouring cells (including itself).
89+
90+ Returns a vector where element `c` contains a vector of scalar indices of neighbouring cells.
91+ """
5392function build_neighbour_cells (ncells:: NTuple{d,Int} ) where {d}
5493 # Create a list of neighbour cells for each cell
5594 neighbourcells = Vector {Vector{Int}} (undef, prod (ncells))
@@ -67,6 +106,10 @@ function build_neighbour_cells(ncells::NTuple{d,Int}) where {d}
67106 return neighbourcells
68107end
69108
109+ """ Construct a `CellList` neighbour list given a box, cutoff `rcut`, and particle count `N`.
110+
111+ Cells are chosen so that their dimensions are at least `rcut`, and neighbour cells are precomputed.
112+ """
70113function CellList (box:: SVector{d,T} , rcut:: T , N:: Int ) where {d,T<: AbstractFloat }
71114
72115 # Calculate cell dimensions ensuring they're >= rcut
@@ -84,6 +127,10 @@ function CellList(box::SVector{d,T}, rcut::T, N::Int) where {d,T<:AbstractFloat}
84127 return CellList (cs, cell_box, ncells, cells, neighbour_cells)
85128end
86129
130+ """ Populate `neighbour_list` (a `CellList`) with particle indices from `system`.
131+
132+ Assigns each particle to its corresponding cell and appends it to that cell's list.
133+ """
87134function build_neighbour_list! (system:: Particles , neighbour_list:: CellList )
88135 # Reset cell list
89136 # foreach(empty!, neighbour_list.cells)
@@ -97,6 +144,10 @@ function build_neighbour_list!(system::Particles, neighbour_list::CellList)
97144 return nothing
98145end
99146
147+ """ Update particle `i` moving from cell `c` to cell `c2` in a `CellList`.
148+
149+ Performs an in-place removal from the old cell and appends to the new one.
150+ """
100151function update_neighbour_list! (i, c, c2, neighbour_list:: CellList )
101152 # Remove from old cell using in-place filter
102153 filter! (x -> x != i, neighbour_list. cells[c])
@@ -110,18 +161,30 @@ end
110161
111162
112163
164+ """ Return the multi-dimensional cell coordinate for position `xi` in `box`.
165+
166+ Result is an `NTuple{d,Int}` giving the cell index in each dimension.
167+ """
113168function get_cell (xi:: SVector{d,T} , box:: SVector{d,T} ) where {d,T<: AbstractFloat }
114169 return ntuple (a -> Int (fld (xi[a], box[a])), d)
115170end
116171
172+ """ Return the multi-dimensional cell coordinate for position `xi` using `neighbour_list` metadata.
173+ """
117174function get_cell (xi:: SVector{d,T} , neighbour_list:: NeighbourList ) where {d,T<: AbstractFloat }
118175 return get_cell (xi, neighbour_list. box)
119176end
120177
178+ """ Return the scalar cell index for position `xi` using `neighbour_list`.
179+ """
121180function get_cell_index (xi:: SVector{d,T} , neighbour_list:: NeighbourList ) where {d,T<: AbstractFloat }
122181 mc = get_cell (xi, neighbour_list)
123182 return cell_index (neighbour_list, mc)
124183end
184+ """ Return the old and new cell indices for particle `i` in `neighbour_list` (CellList).
185+
186+ Used to detect whether a particle has moved between cells.
187+ """
125188function old_new_cell (system:: Particles , i, neighbour_list:: CellList )
126189 c = neighbour_list. cs[i]
127190 # New cell index
@@ -130,6 +193,10 @@ function old_new_cell(system::Particles, i, neighbour_list::CellList)
130193 return c, c2
131194end
132195
196+ """ Linked-list neighbour list implementation.
197+
198+ Uses arrays `head` and `list` to store per-cell linked lists of particle indices.
199+ """
133200struct LinkedList{T<: AbstractFloat , d} <: NeighbourList
134201 cs:: Vector{Int}
135202 box:: SVector{d,T}
@@ -140,6 +207,8 @@ struct LinkedList{T<:AbstractFloat, d} <: NeighbourList
140207 neighbour_cells:: Vector{Vector{Int}}
141208end
142209
210+ """ Construct a `LinkedList` neighbour list given box, cutoff `rcut`, and number of particles `N`.
211+ """
143212function LinkedList (box, rcut, N)
144213 cell = box ./ fld .(box, rcut)
145214 ncells = ntuple (a -> Int (box[a] / cell[a]), length (box))
@@ -151,6 +220,10 @@ function LinkedList(box, rcut, N)
151220end
152221
153222
223+ """ Populate `neighbour_list` (a `LinkedList`) by constructing head/list linked lists per cell.
224+
225+ Resets headers and inserts particles into per-cell linked lists efficiently.
226+ """
154227function build_neighbour_list! (system:: Particles , neighbour_list:: LinkedList )
155228 # Reset the headers
156229 for c in 1 : prod (neighbour_list. ncells)
@@ -172,8 +245,10 @@ function build_neighbour_list!(system::Particles, neighbour_list::LinkedList)
172245 return nothing
173246end
174247
248+ """ Update particle `i` moving from cell `c` to `c2` in a `LinkedList`.
175249
176-
250+ Performs linked-list updates handling header and interior-node cases.
251+ """
177252function update_neighbour_list! (i:: Int , c:: Int , c2:: Int , neighbour_list:: LinkedList )
178253 # Remove particle from old cell (distinguish head or not)
179254 if neighbour_list. head[c] == i
@@ -195,6 +270,8 @@ function update_neighbour_list!(i::Int, c::Int, c2::Int, neighbour_list::LinkedL
195270 return nothing
196271end
197272
273+ """ Return old and new cell indices for particle `i` using a `LinkedList` neighbour list.
274+ """
198275function old_new_cell (system:: Particles , i, neighbour_list:: LinkedList )
199276 c = neighbour_list. cs[i]
200277 # New cell index
0 commit comments