-
Notifications
You must be signed in to change notification settings - Fork 5
/
dictionary.jl
88 lines (67 loc) · 2.69 KB
/
dictionary.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
"""
DictionaryCellList{NDIMS}()
A simple cell list implementation where a cell index `(i, j)` or `(i, j, k)` is mapped to a
`Vector{Int}` by a `Dict`.
By using a dictionary, which only stores non-empty cells, the domain is
potentially infinite.
This implementation is very simple, but it neither uses an optimized hash function
for integer tuples, nor does it use a contiguous memory layout.
Consequently, this cell list is not GPU-compatible.
# Arguments
- `NDIMS`: Number of dimensions.
"""
struct DictionaryCellList{NDIMS} <: AbstractCellList
hashtable :: Dict{NTuple{NDIMS, Int}, Vector{Int}}
empty_vector :: Vector{Int} # Just an empty vector (used in `eachneighbor`)
function DictionaryCellList{NDIMS}() where {NDIMS}
hashtable = Dict{NTuple{NDIMS, Int}, Vector{Int}}()
empty_vector = Int[]
new{NDIMS}(hashtable, empty_vector)
end
end
supported_update_strategies(::DictionaryCellList) = (SemiParallelUpdate, SerialUpdate)
function Base.empty!(cell_list::DictionaryCellList)
Base.empty!(cell_list.hashtable)
return cell_list
end
function push_cell!(cell_list::DictionaryCellList, cell, point)
(; hashtable) = cell_list
if haskey(hashtable, cell)
append!(hashtable[cell], point)
else
hashtable[cell] = [point]
end
return cell_list
end
function deleteat_cell!(cell_list::DictionaryCellList, cell, i)
(; hashtable) = cell_list
# This works for `i::Integer`, `i::AbstractVector`, and even `i::Base.Generator`
if length(hashtable[cell]) <= count(_ -> true, i)
delete_cell!(cell_list, cell)
else
deleteat!(hashtable[cell], i)
end
end
function delete_cell!(cell_list, cell)
delete!(cell_list.hashtable, cell)
end
@inline each_cell_index(cell_list::DictionaryCellList) = keys(cell_list.hashtable)
# For this cell list, this is a `KeySet`, which has to be `collect`ed first to be
# able to be used in a threaded loop.
@inline function each_cell_index_threadable(cell_list::DictionaryCellList)
return collect(each_cell_index(cell_list))
end
@inline function Base.getindex(cell_list::DictionaryCellList, cell)
(; hashtable, empty_vector) = cell_list
# Return an empty vector when `cell_index` is not a key of `hashtable` and
# reuse the empty vector to avoid allocations.
return get(hashtable, cell, empty_vector)
end
@inline function is_correct_cell(::DictionaryCellList, cell_coords, cell_index)
return cell_coords == cell_index
end
@inline index_type(::DictionaryCellList{NDIMS}) where {NDIMS} = NTuple{NDIMS, Int}
function copy_cell_list(::DictionaryCellList{NDIMS}, search_radius,
periodic_box) where {NDIMS}
return DictionaryCellList{NDIMS}()
end