PhysicalTrees.jl
Distributed octrees for N-body simulation
PhysicalTrees.jl is a package in the JuliaAstroSim ecosystem. It builds and queries space-partitioning octrees over particle data, in a way that is
- Unitful — positions, smoothing lengths and box sizes carry their physical units (kpc, Myr, M⊙, …) end to end; unit errors are caught at the call site rather than producing silent nonsense.
- Distributed — the build pipeline is split across multiple workers and the tree is rebuilt in place after data movement.
- Composable — sits on top of PhysicalParticles.jl and re-exports its
PVector,Star,Massless,extentanddatadimension, so the rest of the ecosystem is oneusingaway.
Why an octree?
An N-body simulation needs to evaluate gravity (or SPH kernels) between every pair of nearby particles. A naïve double loop is $\mathcal O(N^2)$; an octree brings this down to $\mathcal O(N\log N)$ by only descending into a node when the field it represents could materially contribute.
Package Features
- Octree construction from raw
PVectors, fromStructArray{<:AbstractParticle}, and from unitless or unitful data. - Multi-worker tree construction via
ParallelOperations. - Neighbor search:
ngb_treefind_variable/ngb_treefind_pairs— single-center cube / sphere search.ngb_treefind_all/ngb_treefind_pairs_all— bulk neighbor list for every local particle (SPH density loop).search_inbox_local/search_inradius_local/search_all_parallel— distributed variants that return per-task export flags so the caller can pull candidates from remote workers.
- Periodic boundary conditions with a minimum-image convention (see
ngb_periodic_diffandcheck_incube_periodic). update_node_len— re-enlarges nodeSideLengths after particles have moved, equivalent to Gadget-2'sforce_update_node_len_local.
Quick start
using PhysicalParticles, PhysicalTrees, Unitful, UnitfulAstro
using Distributed
addprocs(2)
@everywhere using PhysicalParticles, PhysicalTrees, UnitfulAstro
# Six unitful particles in a (-1, 1)³ kpc cube
pos = [PVector( 1.0, 1.0, 1.0, u"kpc"),
PVector(-1.0, -1.0, -1.0, u"kpc"),
PVector( 1.0, 0.0, -1.0, u"kpc"),
PVector(-1.0, 0.0, 1.0, u"kpc"),
PVector( 0.0, 0.0, -1.0, u"kpc"),
PVector(-1.0, 0.0, 0.0, u"kpc")]
particles = StructArray(Star(uAstro) for _ in 1:6)
assign_particles(particles, :Pos, pos)
# Build the tree across workers 1 and 2
tree = octree(particles, pids = workers())
# Find particles inside a unit-radius cube around the origin
ngb = ngb_treefind_variable(PVector(0.0, 0.0, 0.0, u"kpc"), 1.0u"kpc", tree)
# Tear down on all workers when done
unregister(tree)Manual Outline
Library Reference
Package ecosystem
- Basic data structure: PhysicalParticles.jl
- File I/O: AstroIO.jl
- Initial Condition: AstroIC.jl
- Parallelism: ParallelOperations.jl
- Trees: PhysicalTrees.jl
- Meshes: PhysicalMeshes.jl
- Plotting: AstroPlot.jl
- AstroNbodySim.jl — gravitational N-body simulations, glue layer, and parallel runtime
- Simulation of wave dark matter: WaveDM.jl