|
1 | 1 | @testset verbose=true "GridNeighborhoodSearch" begin |
2 | | - @testset "Coordinate Limits" begin |
3 | | - # Test the threshold for very large and very small coordinates. |
| 2 | + @testset "Cells at Coordinate Limits" begin |
| 3 | + # Test the threshold for very large and very small coordinates |
4 | 4 | coords1 = [Inf, -Inf] |
5 | 5 | coords2 = [NaN, 0] |
6 | 6 | coords3 = [typemax(Int) + 1.0, -typemax(Int) - 1.0] |
|
15 | 15 |
|
16 | 16 | @testset "Rectangular Point Cloud 2D" begin |
17 | 17 | #### Setup |
18 | | - # Rectangular filled with equidistant spaced particles |
19 | | - # from (x, y) = (-0.25, -0.25) to (x, y) = (0.35, 0.35) |
| 18 | + # Rectangle of equidistantly spaced particles |
| 19 | + # from (x, y) = (-0.25, -0.25) to (x, y) = (0.35, 0.35). |
20 | 20 | range = -0.25:0.1:0.35 |
21 | 21 | coordinates1 = hcat(collect.(Iterators.product(range, range))...) |
22 | 22 | nparticles = size(coordinates1, 2) |
|
28 | 28 | # Create neighborhood search |
29 | 29 | nhs1 = GridNeighborhoodSearch{2}(radius, nparticles) |
30 | 30 |
|
31 | | - coords_fun(i) = coordinates1[:, i] |
32 | | - initialize_grid!(nhs1, coords_fun) |
| 31 | + initialize_grid!(nhs1, coordinates1) |
33 | 32 |
|
34 | 33 | # Get each neighbor for `particle_position1` |
35 | 34 | neighbors1 = sort(collect(PointNeighbors.eachneighbor(particle_position1, nhs1))) |
|
38 | 37 | coordinates2 = coordinates1 .+ [1.4, -3.5] |
39 | 38 |
|
40 | 39 | # Update neighborhood search |
41 | | - coords_fun2(i) = coordinates2[:, i] |
42 | | - update_grid!(nhs1, coords_fun2) |
| 40 | + update_grid!(nhs1, coordinates2) |
43 | 41 |
|
44 | 42 | # Get each neighbor for updated NHS |
45 | | - neighbors2 = sort(collect(PointNeighbors.eachneighbor(particle_position1, |
46 | | - nhs1))) |
| 43 | + neighbors2 = sort(collect(PointNeighbors.eachneighbor(particle_position1, nhs1))) |
47 | 44 |
|
48 | 45 | # Change position |
49 | 46 | particle_position2 = particle_position1 .+ [1.4, -3.5] |
50 | 47 |
|
51 | 48 | # Get each neighbor for `particle_position2` |
52 | | - neighbors3 = sort(collect(PointNeighbors.eachneighbor(particle_position2, |
53 | | - nhs1))) |
| 49 | + neighbors3 = sort(collect(PointNeighbors.eachneighbor(particle_position2, nhs1))) |
54 | 50 |
|
55 | 51 | # Double search radius |
56 | 52 | nhs2 = GridNeighborhoodSearch{2}(2 * radius, size(coordinates1, 2)) |
57 | | - initialize_grid!(nhs2, coords_fun) |
| 53 | + initialize!(nhs2, coordinates1, coordinates1) |
58 | 54 |
|
59 | 55 | # Get each neighbor in double search radius |
60 | | - neighbors4 = sort(collect(PointNeighbors.eachneighbor(particle_position1, |
61 | | - nhs2))) |
| 56 | + neighbors4 = sort(collect(PointNeighbors.eachneighbor(particle_position1, nhs2))) |
62 | 57 |
|
63 | 58 | # Move particles |
64 | 59 | coordinates2 = coordinates1 .+ [0.4, -0.4] |
65 | 60 |
|
66 | 61 | # Update neighborhood search |
67 | | - update_grid!(nhs2, coords_fun2) |
| 62 | + update!(nhs2, coordinates2, coordinates2) |
68 | 63 |
|
69 | 64 | # Get each neighbor in double search radius |
70 | | - neighbors5 = sort(collect(PointNeighbors.eachneighbor(particle_position1, |
71 | | - nhs2))) |
| 65 | + neighbors5 = sort(collect(PointNeighbors.eachneighbor(particle_position1, nhs2))) |
72 | 66 |
|
73 | | - #### Verification |
| 67 | + #### Verification against lists of potential neighbors built by hand |
74 | 68 | @test neighbors1 == [17, 18, 19, 24, 25, 26, 31, 32, 33] |
75 | 69 |
|
76 | 70 | @test neighbors2 == Int[] |
77 | 71 |
|
78 | 72 | @test neighbors3 == [17, 18, 19, 24, 25, 26, 31, 32, 33] |
79 | 73 |
|
80 | 74 | @test neighbors4 == [ |
81 | | - 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 23, 24, 25, |
82 | | - 26, 27, 28, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 44, 45, 46, 47, |
83 | | - 48, 49] |
| 75 | + 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 30, 31, |
| 76 | + 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 44, 45, 46, 47, 48, 49] |
84 | 77 |
|
85 | 78 | @test neighbors5 == [36, 37, 38, 43, 44, 45] |
86 | 79 | end |
87 | 80 |
|
88 | 81 | @testset "Rectangular Point Cloud 3D" begin |
89 | 82 | #### Setup |
90 | | - # Rectangular filled with equidistant spaced particles |
91 | | - # from (x, y, z) = (-0.25, -0.25, -0.25) to (x, y) = (0.35, 0.35, 0.35) |
| 83 | + # Rectangle of equidistantly spaced particles |
| 84 | + # from (x, y, z) = (-0.25, -0.25, -0.25) to (x, y, z) = (0.35, 0.35, 0.35). |
92 | 85 | range = -0.25:0.1:0.35 |
93 | 86 | coordinates1 = hcat(collect.(Iterators.product(range, range, range))...) |
94 | 87 | nparticles = size(coordinates1, 2) |
|
104 | 97 | initialize_grid!(nhs1, coords_fun) |
105 | 98 |
|
106 | 99 | # Get each neighbor for `particle_position1` |
107 | | - neighbors1 = sort(collect(PointNeighbors.eachneighbor(particle_position1, |
108 | | - nhs1))) |
| 100 | + neighbors1 = sort(collect(PointNeighbors.eachneighbor(particle_position1, nhs1))) |
109 | 101 |
|
110 | 102 | # Move particles |
111 | 103 | coordinates2 = coordinates1 .+ [1.4, -3.5, 0.8] |
|
115 | 107 | update_grid!(nhs1, coords_fun2) |
116 | 108 |
|
117 | 109 | # Get each neighbor for updated NHS |
118 | | - neighbors2 = sort(collect(PointNeighbors.eachneighbor(particle_position1, |
119 | | - nhs1))) |
| 110 | + neighbors2 = sort(collect(PointNeighbors.eachneighbor(particle_position1, nhs1))) |
120 | 111 |
|
121 | 112 | # Change position |
122 | 113 | particle_position2 = particle_position1 .+ [1.4, -3.5, 0.8] |
123 | 114 |
|
124 | 115 | # Get each neighbor for `particle_position2` |
125 | | - neighbors3 = sort(collect(PointNeighbors.eachneighbor(particle_position2, |
126 | | - nhs1))) |
| 116 | + neighbors3 = sort(collect(PointNeighbors.eachneighbor(particle_position2, nhs1))) |
127 | 117 |
|
128 | | - #### Verification |
| 118 | + #### Verification against lists of potential neighbors built by hand |
129 | 119 | @test neighbors1 == |
130 | 120 | [115, 116, 117, 122, 123, 124, 129, 130, 131, 164, 165, 166, 171, 172, |
131 | 121 | 173, 178, 179, 180, 213, 214, 215, 220, 221, 222, 227, 228, 229] |
|
137 | 127 | 173, 178, 179, 180, 213, 214, 215, 220, 221, 222, 227, 228, 229] |
138 | 128 | end |
139 | 129 |
|
140 | | - @testset verbose=true "Periodicity 2D" begin |
141 | | - @testset "Simple Example" begin |
142 | | - coords = [-0.08 0.0 0.18 0.1 -0.08 |
143 | | - -0.12 -0.05 -0.09 0.15 0.39] |
144 | | - |
145 | | - # 3 x 6 cells |
146 | | - nhs = GridNeighborhoodSearch{2}(0.1, size(coords, 2), |
147 | | - periodic_box_min_corner = [-0.1, -0.2], |
148 | | - periodic_box_max_corner = [0.2, 0.4]) |
149 | | - |
150 | | - initialize_grid!(nhs, coords) |
151 | | - |
152 | | - neighbors = [sort(collect(PointNeighbors.eachneighbor(coords[:, i], |
153 | | - nhs))) |
154 | | - for i in 1:5] |
155 | | - |
156 | | - # Note that (1, 2) and (2, 3) are not neighbors, but they are in neighboring cells |
157 | | - @test neighbors[1] == [1, 2, 3, 5] |
158 | | - @test neighbors[2] == [1, 2, 3] |
159 | | - @test neighbors[3] == [1, 2, 3] |
160 | | - @test neighbors[4] == [4] |
161 | | - @test neighbors[5] == [1, 5] |
162 | | - |
163 | | - neighbors_loop = [Int[] for _ in axes(coords, 2)] |
164 | | - |
165 | | - for_particle_neighbor(coords, coords, nhs, |
166 | | - particles = axes(coords, 2)) do particle, |
167 | | - neighbor, |
168 | | - pos_diff, |
169 | | - distance |
170 | | - append!(neighbors_loop[particle], neighbor) |
171 | | - end |
172 | | - |
173 | | - @test sort(neighbors_loop[1]) == [1, 3, 5] |
174 | | - @test sort(neighbors_loop[2]) == [2] |
175 | | - @test sort(neighbors_loop[3]) == [1, 3] |
176 | | - @test sort(neighbors_loop[4]) == [4] |
177 | | - @test sort(neighbors_loop[5]) == [1, 5] |
178 | | - end |
179 | | - |
180 | | - @testset "Rounding Up Cell Sizes" begin |
181 | | - coords = [-0.08 0.0 0.18 0.1 -0.08 |
182 | | - -0.12 -0.05 -0.09 0.15 0.42] |
183 | | - |
184 | | - # 3 x 6 cells |
185 | | - nhs = GridNeighborhoodSearch{2}(0.1, size(coords, 2), |
186 | | - periodic_box_min_corner = [-0.1, -0.2], |
187 | | - periodic_box_max_corner = [0.205, 0.43]) |
| 130 | + @testset verbose=true "Periodicity" begin |
| 131 | + # These setups are the same as in `test/neighborhood_search.jl`, |
| 132 | + # but instead of testing the actual neighbors with `for_particle_neighbor`, |
| 133 | + # we only test the potential neighbors (particles in neighboring cells) here. |
| 134 | + |
| 135 | + # Names, coordinates and corresponding periodic boxes for each test |
| 136 | + names = [ |
| 137 | + "Simple Example 2D", |
| 138 | + "Box Not Multiple of Search Radius 2D", |
| 139 | + "Simple Example 3D", |
| 140 | + ] |
| 141 | + |
| 142 | + coordinates = [ |
| 143 | + [-0.08 0.0 0.18 0.1 -0.08 |
| 144 | + -0.12 -0.05 -0.09 0.15 0.39], |
| 145 | + [-0.08 0.0 0.18 0.1 -0.08 |
| 146 | + -0.12 -0.05 -0.09 0.15 0.42], |
| 147 | + [-0.08 0.0 0.18 0.1 -0.08 |
| 148 | + -0.12 -0.05 -0.09 0.15 0.39 |
| 149 | + 0.14 0.34 0.12 0.06 0.13], |
| 150 | + ] |
| 151 | + |
| 152 | + periodic_boxes = [ |
| 153 | + ([-0.1, -0.2], [0.2, 0.4]), |
| 154 | + # The `GridNeighborhoodSearch` is forced to round up the cell sizes in this test |
| 155 | + # to avoid split cells. |
| 156 | + ([-0.1, -0.2], [0.205, 0.43]), |
| 157 | + ([-0.1, -0.2, 0.05], [0.2, 0.4, 0.35]), |
| 158 | + ] |
| 159 | + |
| 160 | + @testset verbose=true "$(names[i])" for i in eachindex(names) |
| 161 | + coords = coordinates[i] |
| 162 | + |
| 163 | + nhs = GridNeighborhoodSearch{size(coords, 1)}(0.1, size(coords, 2), |
| 164 | + periodic_box_min_corner = periodic_boxes[i][1], |
| 165 | + periodic_box_max_corner = periodic_boxes[i][2]) |
188 | 166 |
|
189 | 167 | initialize_grid!(nhs, coords) |
190 | 168 |
|
191 | | - neighbors = [sort(collect(PointNeighbors.eachneighbor(coords[:, i], |
192 | | - nhs))) |
| 169 | + neighbors = [sort(collect(PointNeighbors.eachneighbor(coords[:, i], nhs))) |
193 | 170 | for i in 1:5] |
194 | 171 |
|
195 | 172 | # Note that (1, 2) and (2, 3) are not neighbors, but they are in neighboring cells |
|
198 | 175 | @test neighbors[3] == [1, 2, 3] |
199 | 176 | @test neighbors[4] == [4] |
200 | 177 | @test neighbors[5] == [1, 5] |
201 | | - |
202 | | - neighbors_loop = [Int[] for _ in axes(coords, 2)] |
203 | | - |
204 | | - for_particle_neighbor(coords, coords, nhs, |
205 | | - particles = axes(coords, 2)) do particle, |
206 | | - neighbor, |
207 | | - pos_diff, |
208 | | - distance |
209 | | - append!(neighbors_loop[particle], neighbor) |
210 | | - end |
211 | | - |
212 | | - @test sort(neighbors_loop[1]) == [1, 3, 5] |
213 | | - @test sort(neighbors_loop[2]) == [2] |
214 | | - @test sort(neighbors_loop[3]) == [1, 3] |
215 | | - @test sort(neighbors_loop[4]) == [4] |
216 | | - @test sort(neighbors_loop[5]) == [1, 5] |
217 | 178 | end |
218 | 179 |
|
219 | 180 | @testset "Offset Domain Triggering Split Cells" begin |
220 | | - # This used to trigger a "split cell bug", where the left and right boundary |
221 | | - # cells were only partially contained in the domain. |
222 | | - # The left particle was placed inside a ghost cells, which causes it to not |
223 | | - # see the right particle, even though it is within the search distance. |
| 181 | + # This test used to trigger a "split cell bug", where the left and right |
| 182 | + # boundary cells were only partially contained in the domain. |
| 183 | + # The left particle was placed inside a ghost cells, which caused it to not |
| 184 | + # see the right particle, even though it was within the search distance. |
224 | 185 | # The domain size is an integer multiple of the cell size, but the NHS did not |
225 | 186 | # offset the grid based on the domain position. |
226 | | - # See https://github.com/trixi-framework/PointNeighbors.jl/pull/211 |
| 187 | + # See https://github.com/trixi-framework/TrixiParticles.jl/pull/211 |
227 | 188 | # for a more detailed explanation. |
228 | 189 | coords = [-1.4 1.9 |
229 | 190 | 0.0 0.0] |
|
244 | 205 | @test neighbors[2] == [1, 2] |
245 | 206 | end |
246 | 207 | end |
247 | | - |
248 | | - @testset verbose=true "Periodicity 3D" begin |
249 | | - coords = [-0.08 0.0 0.18 0.1 -0.08 |
250 | | - -0.12 -0.05 -0.09 0.15 0.39 |
251 | | - 0.14 0.34 0.12 0.06 0.13] |
252 | | - |
253 | | - # 3 x 6 x 3 cells |
254 | | - nhs = GridNeighborhoodSearch{3}(0.1, size(coords, 2), |
255 | | - periodic_box_min_corner = [-0.1, -0.2, 0.05], |
256 | | - periodic_box_max_corner = [0.2, 0.4, 0.35]) |
257 | | - |
258 | | - initialize_grid!(nhs, coords) |
259 | | - |
260 | | - neighbors = [sort(collect(PointNeighbors.eachneighbor(coords[:, i], nhs))) |
261 | | - for i in 1:5] |
262 | | - |
263 | | - # Note that (1, 2) and (2, 3) are not neighbors, but they are in neighboring cells |
264 | | - @test neighbors[1] == [1, 2, 3, 5] |
265 | | - @test neighbors[2] == [1, 2, 3] |
266 | | - @test neighbors[3] == [1, 2, 3] |
267 | | - @test neighbors[4] == [4] |
268 | | - @test neighbors[5] == [1, 5] |
269 | | - |
270 | | - neighbors_loop = [Int[] for _ in axes(coords, 2)] |
271 | | - |
272 | | - for_particle_neighbor(coords, coords, |
273 | | - nhs) do particle, neighbor, pos_diff, distance |
274 | | - append!(neighbors_loop[particle], neighbor) |
275 | | - end |
276 | | - |
277 | | - @test sort(neighbors_loop[1]) == [1, 3, 5] |
278 | | - @test sort(neighbors_loop[2]) == [2] |
279 | | - @test sort(neighbors_loop[3]) == [1, 3] |
280 | | - @test sort(neighbors_loop[4]) == [4] |
281 | | - @test sort(neighbors_loop[5]) == [1, 5] |
282 | | - end |
283 | | -end |
| 208 | +end; |
0 commit comments