Skip to content

Commit

Permalink
Add tests from TrixiParticles.jl
Browse files Browse the repository at this point in the history
  • Loading branch information
efaulhaber committed May 4, 2024
1 parent 1ca53b4 commit 0c8eb53
Show file tree
Hide file tree
Showing 3 changed files with 298 additions and 1 deletion.
284 changes: 284 additions & 0 deletions test/grid_nhs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
@testset verbose=true "GridNeighborhoodSearch" begin
@testset "Coordinate Limits" begin
# Test the threshold for very large and very small coordinates.
coords1 = [Inf, -Inf]
coords2 = [NaN, 0]
coords3 = [typemax(Int) + 1.0, -typemax(Int) - 1.0]

@test TrixiNeighborhoodSearch.cell_coords(coords1, nothing, (1.0, 1.0)) ==
(typemax(Int), typemin(Int))
@test TrixiNeighborhoodSearch.cell_coords(coords2, nothing, (1.0, 1.0)) ==
(typemax(Int), 0)
@test TrixiNeighborhoodSearch.cell_coords(coords3, nothing, (1.0, 1.0)) ==
(typemax(Int), typemin(Int))
end

@testset "Rectangular Point Cloud 2D" begin
#### Setup
# Rectangular filled with equidistant spaced particles
# from (x, y) = (-0.25, -0.25) to (x, y) = (0.35, 0.35)
range = -0.25:0.1:0.35
coordinates1 = hcat(collect.(Iterators.product(range, range))...)
nparticles = size(coordinates1, 2)

particle_position1 = [0.05, 0.05]
particle_spacing = 0.1
radius = particle_spacing

# Create neighborhood search
nhs1 = GridNeighborhoodSearch{2}(radius, nparticles)

coords_fun(i) = coordinates1[:, i]
initialize!(nhs1, coords_fun)

# Get each neighbor for `particle_position1`
neighbors1 = sort(collect(TrixiNeighborhoodSearch.eachneighbor(particle_position1,
nhs1)))

# Move particles
coordinates2 = coordinates1 .+ [1.4, -3.5]

# Update neighborhood search
coords_fun2(i) = coordinates2[:, i]
update!(nhs1, coords_fun2)

# Get each neighbor for updated NHS
neighbors2 = sort(collect(TrixiNeighborhoodSearch.eachneighbor(particle_position1,
nhs1)))

# Change position
particle_position2 = particle_position1 .+ [1.4, -3.5]

# Get each neighbor for `particle_position2`
neighbors3 = sort(collect(TrixiNeighborhoodSearch.eachneighbor(particle_position2,
nhs1)))

# Double search radius
nhs2 = GridNeighborhoodSearch{2}(2 * radius, size(coordinates1, 2))
initialize!(nhs2, coords_fun)

# Get each neighbor in double search radius
neighbors4 = sort(collect(TrixiNeighborhoodSearch.eachneighbor(particle_position1,
nhs2)))

# Move particles
coordinates2 = coordinates1 .+ [0.4, -0.4]

# Update neighborhood search
update!(nhs2, coords_fun2)

# Get each neighbor in double search radius
neighbors5 = sort(collect(TrixiNeighborhoodSearch.eachneighbor(particle_position1,
nhs2)))

#### Verification
@test neighbors1 == [17, 18, 19, 24, 25, 26, 31, 32, 33]

@test neighbors2 == Int[]

@test neighbors3 == [17, 18, 19, 24, 25, 26, 31, 32, 33]

@test neighbors4 == [
9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 23, 24, 25,
26, 27, 28, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 44, 45, 46, 47,
48, 49]

@test neighbors5 == [36, 37, 38, 43, 44, 45]
end

@testset "Rectangular Point Cloud 3D" begin
#### Setup
# Rectangular filled with equidistant spaced particles
# from (x, y, z) = (-0.25, -0.25, -0.25) to (x, y) = (0.35, 0.35, 0.35)
range = -0.25:0.1:0.35
coordinates1 = hcat(collect.(Iterators.product(range, range, range))...)
nparticles = size(coordinates1, 2)

particle_position1 = [0.05, 0.05, 0.05]
particle_spacing = 0.1
radius = particle_spacing

# Create neighborhood search
nhs1 = GridNeighborhoodSearch{3}(radius, nparticles)

coords_fun(i) = coordinates1[:, i]
initialize!(nhs1, coords_fun)

# Get each neighbor for `particle_position1`
neighbors1 = sort(collect(TrixiNeighborhoodSearch.eachneighbor(particle_position1,
nhs1)))

# Move particles
coordinates2 = coordinates1 .+ [1.4, -3.5, 0.8]

# Update neighborhood search
coords_fun2(i) = coordinates2[:, i]
update!(nhs1, coords_fun2)

# Get each neighbor for updated NHS
neighbors2 = sort(collect(TrixiNeighborhoodSearch.eachneighbor(particle_position1,
nhs1)))

# Change position
particle_position2 = particle_position1 .+ [1.4, -3.5, 0.8]

# Get each neighbor for `particle_position2`
neighbors3 = sort(collect(TrixiNeighborhoodSearch.eachneighbor(particle_position2,
nhs1)))

#### Verification
@test neighbors1 ==
[115, 116, 117, 122, 123, 124, 129, 130, 131, 164, 165, 166, 171, 172,
173, 178, 179, 180, 213, 214, 215, 220, 221, 222, 227, 228, 229]

@test neighbors2 == Int[]

@test neighbors3 ==
[115, 116, 117, 122, 123, 124, 129, 130, 131, 164, 165, 166, 171, 172,
173, 178, 179, 180, 213, 214, 215, 220, 221, 222, 227, 228, 229]
end

@testset verbose=true "Periodicity 2D" begin
@testset "Simple Example" begin
coords = [-0.08 0.0 0.18 0.1 -0.08
-0.12 -0.05 -0.09 0.15 0.39]

# 3 x 6 cells
nhs = GridNeighborhoodSearch{2}(0.1, size(coords, 2),
periodic_box_min_corner = [-0.1, -0.2],
periodic_box_max_corner = [0.2, 0.4])

initialize!(nhs, coords)

neighbors = [sort(collect(TrixiNeighborhoodSearch.eachneighbor(coords[:, i],
nhs)))
for i in 1:5]

# Note that (1, 2) and (2, 3) are not neighbors, but they are in neighboring cells
@test neighbors[1] == [1, 2, 3, 5]
@test neighbors[2] == [1, 2, 3]
@test neighbors[3] == [1, 2, 3]
@test neighbors[4] == [4]
@test neighbors[5] == [1, 5]

neighbors_loop = [Int[] for _ in axes(coords, 2)]

for_particle_neighbor(coords, coords, nhs,
particles = axes(coords, 2)) do particle,
neighbor,
pos_diff,
distance
append!(neighbors_loop[particle], neighbor)
end

@test sort(neighbors_loop[1]) == [1, 3, 5]
@test sort(neighbors_loop[2]) == [2]
@test sort(neighbors_loop[3]) == [1, 3]
@test sort(neighbors_loop[4]) == [4]
@test sort(neighbors_loop[5]) == [1, 5]
end

@testset "Rounding Up Cell Sizes" begin
coords = [-0.08 0.0 0.18 0.1 -0.08
-0.12 -0.05 -0.09 0.15 0.42]

# 3 x 6 cells
nhs = GridNeighborhoodSearch{2}(0.1, size(coords, 2),
periodic_box_min_corner = [-0.1, -0.2],
periodic_box_max_corner = [0.205, 0.43])

initialize!(nhs, coords)

neighbors = [sort(collect(TrixiNeighborhoodSearch.eachneighbor(coords[:, i],
nhs)))
for i in 1:5]

# Note that (1, 2) and (2, 3) are not neighbors, but they are in neighboring cells
@test neighbors[1] == [1, 2, 3, 5]
@test neighbors[2] == [1, 2, 3]
@test neighbors[3] == [1, 2, 3]
@test neighbors[4] == [4]
@test neighbors[5] == [1, 5]

neighbors_loop = [Int[] for _ in axes(coords, 2)]

for_particle_neighbor(coords, coords, nhs,
particles = axes(coords, 2)) do particle,
neighbor,
pos_diff,
distance
append!(neighbors_loop[particle], neighbor)
end

@test sort(neighbors_loop[1]) == [1, 3, 5]
@test sort(neighbors_loop[2]) == [2]
@test sort(neighbors_loop[3]) == [1, 3]
@test sort(neighbors_loop[4]) == [4]
@test sort(neighbors_loop[5]) == [1, 5]
end

@testset "Offset Domain Triggering Split Cells" begin
# This used to trigger a "split cell bug", where the left and right boundary
# cells were only partially contained in the domain.
# The left particle was placed inside a ghost cells, which causes it to not
# see the right particle, even though it is within the search distance.
# The domain size is an integer multiple of the cell size, but the NHS did not
# offset the grid based on the domain position.
# See https://github.com/trixi-framework/TrixiNeighborhoodSearch.jl/pull/211
# for a more detailed explanation.
coords = [-1.4 1.9
0.0 0.0]

# 5 x 1 cells
nhs = GridNeighborhoodSearch{2}(1.0, size(coords, 2),
periodic_box_min_corner = [-1.5, 0.0],
periodic_box_max_corner = [2.5, 3.0])

initialize!(nhs, coords)

neighbors = [sort(unique(collect(TrixiNeighborhoodSearch.eachneighbor(coords[:,
i],
nhs))))
for i in 1:2]

@test neighbors[1] == [1, 2]
@test neighbors[2] == [1, 2]
end
end

@testset verbose=true "Periodicity 3D" begin
coords = [-0.08 0.0 0.18 0.1 -0.08
-0.12 -0.05 -0.09 0.15 0.39
0.14 0.34 0.12 0.06 0.13]

# 3 x 6 x 3 cells
nhs = GridNeighborhoodSearch{3}(0.1, size(coords, 2),
periodic_box_min_corner = [-0.1, -0.2, 0.05],
periodic_box_max_corner = [0.2, 0.4, 0.35])

initialize!(nhs, coords)

neighbors = [sort(collect(TrixiNeighborhoodSearch.eachneighbor(coords[:, i], nhs)))
for i in 1:5]

# Note that (1, 2) and (2, 3) are not neighbors, but they are in neighboring cells
@test neighbors[1] == [1, 2, 3, 5]
@test neighbors[2] == [1, 2, 3]
@test neighbors[3] == [1, 2, 3]
@test neighbors[4] == [4]
@test neighbors[5] == [1, 5]

neighbors_loop = [Int[] for _ in axes(coords, 2)]

for_particle_neighbor(coords, coords,
nhs) do particle, neighbor, pos_diff, distance
append!(neighbors_loop[particle], neighbor)
end

@test sort(neighbors_loop[1]) == [1, 3, 5]
@test sort(neighbors_loop[2]) == [2]
@test sort(neighbors_loop[3]) == [1, 3]
@test sort(neighbors_loop[4]) == [4]
@test sort(neighbors_loop[5]) == [1, 5]
end
end
5 changes: 4 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
include("test_util.jl")

@testset verbose=true "TrixiNeighborhoodSearch.jl Tests" begin end
@testset verbose=true "TrixiNeighborhoodSearch.jl Tests" begin
include("trivial_nhs.jl")
include("grid_nhs.jl")
end
10 changes: 10 additions & 0 deletions test/trivial_nhs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@testset verbose=true "TrivialNeighborhoodSearch" begin
# Setup with 5 particles
nhs = TrivialNeighborhoodSearch{2}(1.0, Base.OneTo(5))

# Get each neighbor for arbitrary coordinates
neighbors = collect(TrixiNeighborhoodSearch.eachneighbor([1.0, 2.0], nhs))

#### Verification
@test neighbors == [1, 2, 3, 4, 5]
end

0 comments on commit 0c8eb53

Please sign in to comment.