Skip to content

Commit c510bd5

Browse files
committed
Merge branch 'main' into ef/neighbor-lists-vectorofvectors
2 parents 7427085 + b6d11e6 commit c510bd5

37 files changed

+2637
-570
lines changed

.github/workflows/FormatCheck.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
#
2626
# julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter", version = "0.13.0"))'
2727
run: |
28-
julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter", version="1.0.45"))'
28+
julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter", version="2.1.2"))'
2929
julia -e 'using JuliaFormatter; format(".")'
3030
- name: Format check
3131
run: |

.github/workflows/SpellCheck.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ jobs:
1010
- name: Checkout Actions Repository
1111
uses: actions/checkout@v4
1212
- name: Check spelling
13-
uses: crate-ci/typos@v1.21.0
13+
uses: crate-ci/typos@v1.31.2

.github/workflows/ci.yml

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,58 +34,69 @@ concurrency:
3434

3535
jobs:
3636
build:
37-
name: Run Tests (Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }})
38-
runs-on: ubuntu-latest
37+
name: Run Tests (Julia ${{ matrix.version }} - ${{ matrix.os }})
38+
runs-on: ${{ matrix.os }}
3939
strategy:
4040
# Don't cancel all running jobs when one job fails
4141
fail-fast: false
4242
matrix:
4343
version:
44-
- '1.9'
45-
- '1'
44+
- 'min' # the earliest supported version compatible with the project
45+
- '1' # the latest stable 1.x release
4646
os:
4747
- ubuntu-latest
48-
arch:
49-
- x64
50-
include:
51-
# Also run tests on Windows and macOS-ARM, but only with the latest Julia version
52-
- version: '1'
53-
os: windows-latest
54-
arch: x64
55-
- version: '1'
56-
os: macos-14
57-
arch: arm64
48+
- windows-latest
49+
- macos-14
5850

5951
steps:
6052
- name: Check out project
6153
uses: actions/checkout@v4
54+
6255
- name: Set up Julia
6356
uses: julia-actions/setup-julia@v2
6457
with:
6558
version: ${{ matrix.version }}
66-
- run: julia -e 'using InteractiveUtils; versioninfo(verbose=true)'
59+
60+
- name: Display Julia version
61+
run: julia -e 'using InteractiveUtils; versioninfo(verbose=true)'
62+
6763
- uses: julia-actions/cache@v2
64+
6865
- name: Build package
6966
uses: julia-actions/julia-buildpkg@v1
70-
- name: Run tests
67+
68+
- name: Run unit tests
7169
uses: julia-actions/julia-runtest@v1
7270
with:
7371
annotate: true
7472
# Only run coverage in one Job (Ubuntu and latest Julia version)
7573
coverage: ${{ matrix.os == 'ubuntu-latest' && matrix.version == '1' }}
74+
env:
75+
POINTNEIGHBORS_TEST: unit
76+
7677
- name: Process coverage results
7778
# Only run coverage in one Job (Ubuntu and latest Julia version)
7879
if: matrix.os == 'ubuntu-latest' && matrix.version == '1'
7980
uses: julia-actions/julia-processcoverage@v1
8081
with:
8182
directories: src,test
83+
8284
- name: Upload coverage report to Codecov
8385
# Only run coverage in one Job (Ubuntu and latest Julia version)
8486
if: matrix.os == 'ubuntu-latest' && matrix.version == '1'
85-
uses: codecov/codecov-action@v4
87+
uses: codecov/codecov-action@v5
8688
with:
8789
files: lcov.info
8890
fail_ci_if_error: true
8991
flags: unit
9092
env:
9193
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
94+
95+
- name: Run benchmark tests
96+
uses: julia-actions/julia-runtest@v1
97+
with:
98+
annotate: true
99+
coverage: false
100+
env:
101+
POINTNEIGHBORS_TEST: benchmarks
102+

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ coverage_report/
99
*.jl.*.cov
1010
.vscode/
1111
run
12+
out/*
1213

1314
.DS_Store
1415

.zenodo.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"description": "Neighborhood search with fixed search radius in Julia",
3+
"license": "MIT",
4+
"title": "PointNeighbors.jl",
5+
"upload_type": "software",
6+
"creators": [
7+
{
8+
"affiliation": "Department of Mathematics and Computer Science, University of Cologne, Germany",
9+
"name": "Faulhaber, Erik",
10+
"orcid": "0000-0001-9788-5949"
11+
},
12+
{
13+
"affiliation": "High-Performance Computing Center Stuttgart, University of Stuttgart, Germany",
14+
"name": "Neher, Niklas",
15+
"orcid": "0009-0004-2472-0923"
16+
},
17+
{
18+
"affiliation": "Institute of Surface Science, Helmholtz-Zentrum hereon, Germany",
19+
"name": "Berger, Sven",
20+
"orcid": "0000-0001-6083-7038"
21+
},
22+
{
23+
"affiliation": "High-Performance Scientific Computing, University of Augsburg, Germany",
24+
"name": "Schlottke-Lakemper, Michael",
25+
"orcid": "0000-0002-3195-2536"
26+
},
27+
{
28+
"affiliation": "Department of Mathematics and Computer Science, University of Cologne, Germany",
29+
"name": "Gassner, Gregor J.",
30+
"orcid": "0000-0002-1752-1158"
31+
}
32+
],
33+
"access_right": "open"
34+
}

Project.toml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
name = "PointNeighbors"
22
uuid = "1c4d5385-0a27-49de-8e2c-43b175c8985c"
33
authors = ["Erik Faulhaber <[email protected]>"]
4-
version = "0.2.4-dev"
4+
version = "0.6.3"
55

66
[deps]
7+
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
78
ArraysOfArrays = "65a8f2f4-9b39-5baf-92e2-a9cc46fdf018"
9+
Atomix = "a9b6321e-bd34-4604-b9c9-b65b8de01458"
10+
GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527"
11+
KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
812
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
913
Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588"
1014
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
1115
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1216

1317
[compat]
18+
Adapt = "4"
1419
ArraysOfArrays = "0.6"
20+
Atomix = "1"
21+
GPUArraysCore = "0.2"
22+
KernelAbstractions = "0.9"
1523
LinearAlgebra = "1"
1624
Polyester = "0.7.5"
1725
Reexport = "1"
1826
StaticArrays = "1"
19-
julia = "1.9"
27+
julia = "1.10"

README.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,63 @@
88
[![Codecov](https://codecov.io/gh/trixi-framework/PointNeighbors.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/trixi-framework/PointNeighbors.jl)
99
[![SciML Code Style](https://img.shields.io/static/v1?label=code%20style&message=SciML&color=9558b2&labelColor=389826)](https://github.com/SciML/SciMLStyle)
1010
[![License: MIT](https://img.shields.io/badge/License-MIT-success.svg)](https://opensource.org/license/mit/)
11+
[![DOI](https://zenodo.org/badge/doi/10.5281/zenodo.12702157.svg)](https://zenodo.org/doi/10.5281/zenodo.12702157)
1112

12-
Work in Progress!
13+
**PointNeighbors.jl** is a package for neighborhood search with fixed search radius in
14+
1D, 2D and 3D point clouds.
15+
16+
## Features
17+
18+
- Several implementations of neighborhood search with fixed search radius
19+
- Focus on fast incremental updates to be usable for particle-based simulations with
20+
frequent updates
21+
- Designed as a "playground" to easily switch between different implementations and data
22+
structures
23+
- Common API over all implementations
24+
- Extensive benchmark suite to study different implementations (work in progress)
25+
- GPU compatibility (work in progress)
26+
27+
| Implementation | Description | Features | Query | Update | GPU-compatible |
28+
| ------------- | ------------- | --- | :--: | :--: | :--: |
29+
| `GridNeighborhoodSearch` with `DictionaryCellList` | Grid-based NHS with Julia `Dict` backend | Infinite domain | Fast | Fast ||
30+
| `GridNeighborhoodSearch` with `FullGridCellList` | Grid-based NHS allocating all cells of the domain | Finite domain, but efficient memory layout for densely filled domain. | Faster | Fastest ||
31+
| `PrecomputedNeighborhoodSearch` | Precompute neighbor lists | Best for [TLSPH](https://trixi-framework.github.io/TrixiParticles.jl/stable/systems/total_lagrangian_sph/) without NHS updates. Not suitable for updates in every time step. | Fastest | Very slow ||
32+
33+
## Benchmarks
34+
35+
The following benchmarks were conducted on an AMD Ryzen Threadripper 3990X using 128 threads.
36+
37+
Benchmark of a single force computation step of a Weakly Compressible SPH (WCSPH) simulation:
38+
![wcsph](https://github.com/trixi-framework/PointNeighbors.jl/assets/44124897/ad5c378b-9ce2-4e6f-91dc-1e0da379b91f)
39+
40+
Benchmark of an incremental update similar to a WCSPH simulation (note the log scale):
41+
![update](https://github.com/trixi-framework/PointNeighbors.jl/assets/44124897/71eac5c9-6aa5-4267-bc0b-4057c89f8b12)
42+
43+
Benchmark of a full right-hand side evaluation of a WCSPH simulation (note the log scale):
44+
![rhs](https://github.com/trixi-framework/PointNeighbors.jl/assets/44124897/ac328a96-1b9f-4319-a785-dce9d862fd70)
45+
46+
47+
## Packages using PointNeighbors.jl
48+
49+
- [TrixiParticles.jl](https://github.com/trixi-framework/TrixiParticles.jl)
50+
- [Peridynamics.jl](https://github.com/kaipartmann/Peridynamics.jl)
51+
- [PeriLab.jl](https://github.com/PeriHub/PeriLab.jl)
52+
53+
If you're using PointNeighbors.jl in your package, please feel free to open a PR adding it
54+
to this list.
55+
56+
57+
## Cite Us
58+
59+
If you use PointNeighbors.jl in your own research or write a paper using results obtained
60+
with the help of PointNeighbors.jl, please cite it as
61+
```bibtex
62+
@misc{pointneighbors,
63+
title={{P}oint{N}eighbors.jl: {N}eighborhood search with fixed search radius in {J}ulia},
64+
author={Erik Faulhaber and Niklas Neher and Sven Berger and
65+
Michael Schlottke-Lakemper and Gregor Gassner},
66+
year={2024},
67+
howpublished={\url{https://github.com/trixi-framework/PointNeighbors.jl}},
68+
doi={10.5281/zenodo.12702157}
69+
}
70+
```

benchmarks/benchmarks.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
include("count_neighbors.jl")
2+
include("n_body.jl")
3+
include("smoothed_particle_hydrodynamics.jl")
4+
include("update.jl")
5+
6+
include("plot.jl")

benchmarks/count_neighbors.jl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using PointNeighbors
2+
using BenchmarkTools
3+
4+
"""
5+
benchmark_count_neighbors(neighborhood_search, coordinates; parallel = true)
6+
7+
A very cheap and simple neighborhood search benchmark, only counting the neighbors of each
8+
point. For each point-neighbor pair, only an array entry is incremented.
9+
10+
Due to the minimal computational cost, differences between neighborhood search
11+
implementations are highlighted. On the other hand, this is the least realistic benchmark.
12+
13+
For a computationally heavier benchmark, see [`benchmark_n_body`](@ref).
14+
"""
15+
function benchmark_count_neighbors(neighborhood_search, coordinates;
16+
parallelization_backend = default_backend(coordinates))
17+
n_neighbors = zeros(Int, size(coordinates, 2))
18+
19+
function count_neighbors!(n_neighbors, coordinates, neighborhood_search,
20+
parallelization_backend)
21+
n_neighbors .= 0
22+
23+
foreach_point_neighbor(coordinates, coordinates, neighborhood_search;
24+
parallelization_backend) do i, _, _, _
25+
n_neighbors[i] += 1
26+
end
27+
end
28+
29+
return @belapsed $count_neighbors!($n_neighbors, $coordinates,
30+
$neighborhood_search, $parallelization_backend)
31+
end

benchmarks/n_body.jl

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using PointNeighbors
2+
using BenchmarkTools
3+
4+
"""
5+
benchmark_n_body(neighborhood_search, coordinates; parallel = true)
6+
7+
A simple neighborhood search benchmark, computing the right-hand side of an n-body
8+
simulation with a cutoff (corresponding to the search radius of `neighborhood_search`).
9+
10+
This is a more realistic benchmark for particle-based simulations than
11+
[`benchmark_count_neighbors`](@ref).
12+
However, due to the higher computational cost, differences between neighborhood search
13+
implementations are less pronounced.
14+
"""
15+
function benchmark_n_body(neighborhood_search, coordinates_;
16+
parallelization_backend = default_backend(coordinates_))
17+
# Passing a different backend like `CUDA.CUDABackend`
18+
# allows us to change the type of the array to run the benchmark on the GPU.
19+
# Passing `parallel = true` or `parallel = false` will not change anything here.
20+
coordinates = PointNeighbors.Adapt.adapt(parallelization_backend, coordinates_)
21+
nhs = PointNeighbors.Adapt.adapt(parallelization_backend, neighborhood_search)
22+
23+
# This preserves the data type of `coordinates`, which makes it work for GPU types
24+
mass = 1e10 * (rand!(similar(coordinates, size(coordinates, 2))) .+ 1)
25+
G = 6.6743e-11
26+
27+
dv = similar(coordinates)
28+
29+
function compute_acceleration!(dv, coordinates, mass, G, neighborhood_search,
30+
parallelization_backend)
31+
dv .= 0.0
32+
33+
foreach_point_neighbor(coordinates, coordinates, neighborhood_search;
34+
parallelization_backend) do i, j, pos_diff, distance
35+
# Only consider particles with a distance > 0
36+
distance < sqrt(eps()) && return
37+
38+
dv_ = -G * mass[j] * pos_diff / distance^3
39+
40+
for dim in axes(dv, 1)
41+
@inbounds dv[dim, i] += dv_[dim]
42+
end
43+
end
44+
45+
return dv
46+
end
47+
48+
return @belapsed $compute_acceleration!($dv, $coordinates, $mass, $G, $nhs,
49+
$parallelization_backend)
50+
end

0 commit comments

Comments
 (0)